diff --git a/example/cpp/CMakeLists.txt b/example/cpp/CMakeLists.txt index 234d504d8..b3c6878a0 100644 --- a/example/cpp/CMakeLists.txt +++ b/example/cpp/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +cmake_minimum_required(VERSION 3.4 FATAL_ERROR) project(TdExample VERSION 1.0 LANGUAGES CXX) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 772cf3622..134de548d 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -803,8 +803,8 @@ foundMessages total_count:int32 messages:vector next_offset:string = Fo //@description Describes a sponsored message @id Unique sponsored message identifier @sponsor_chat_id Chat identifier -//@start_parameter Parameter for the bot start message if the sponsored chat is a chat with a bot @content Content of the message -sponsoredMessage id:int32 sponsor_chat_id:int53 start_parameter:string content:MessageContent = SponsoredMessage; +//@link An internal link to be opened when the sponsored message is clicked; may be null. If null, the sponsor chat needs to be opened instead @content Content of the message +sponsoredMessage id:int32 sponsor_chat_id:int53 link:InternalLinkType content:MessageContent = SponsoredMessage; //@description Contains a list of sponsored messages @messages List of sponsored messages sponsoredMessages messages:vector = SponsoredMessages; @@ -1479,11 +1479,11 @@ date day:int32 month:int32 year:int32 = Date; //@birthdate Birthdate of the user @gender Gender of the user, "male" or "female" @country_code A two-letter ISO 3166-1 alpha-2 country code of the user's country @residence_country_code A two-letter ISO 3166-1 alpha-2 country code of the user's residence country personalDetails first_name:string middle_name:string last_name:string native_first_name:string native_middle_name:string native_last_name:string birthdate:date gender:string country_code:string residence_country_code:string = PersonalDetails; -//@description An identity document @number Document number; 1-24 characters @expiry_date Document expiry date; may be null @front_side Front side of the document +//@description An identity document @number Document number; 1-24 characters @expiry_date Document expiry date; may be null if not applicable @front_side Front side of the document //@reverse_side Reverse side of the document; only for driver license and identity card; may be null @selfie Selfie with the document; may be null @translation List of files containing a certified English translation of the document identityDocument number:string expiry_date:date front_side:datedFile reverse_side:datedFile selfie:datedFile translation:vector = IdentityDocument; -//@description An identity document to be saved to Telegram Passport @number Document number; 1-24 characters @expiry_date Document expiry date, if available @front_side Front side of the document +//@description An identity document to be saved to Telegram Passport @number Document number; 1-24 characters @expiry_date Document expiry date; pass null if not applicable @front_side Front side of the document //@reverse_side Reverse side of the document; only for driver license and identity card; pass null otherwise @selfie Selfie with the document; pass null if unavailable @translation List of files containing a certified English translation of the document inputIdentityDocument number:string expiry_date:date front_side:InputFile reverse_side:InputFile selfie:InputFile translation:vector = InputIdentityDocument; diff --git a/td/generate/tl-parser/CMakeLists.txt b/td/generate/tl-parser/CMakeLists.txt index 442ce674a..6cf5331f4 100644 --- a/td/generate/tl-parser/CMakeLists.txt +++ b/td/generate/tl-parser/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) +if (POLICY CMP0065) + # do not export symbols from executables + # affects compiler checks in project(), so must be set before it + cmake_policy(SET CMP0065 NEW) +endif() + project(tl-parser LANGUAGES C) set(SOURCES crc32.h crc32.c tlc.c tl-parser.c tl-parser.h tl-parser-tree.h tl-tl.h portable_endian.h) diff --git a/td/telegram/AnimationsManager.cpp b/td/telegram/AnimationsManager.cpp index 0b0863585..3d8b589b8 100644 --- a/td/telegram/AnimationsManager.cpp +++ b/td/telegram/AnimationsManager.cpp @@ -703,9 +703,7 @@ void AnimationsManager::add_saved_animation(const tl_object_ptr &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); // TODO invokeAfter and log event auto file_view = td_->file_manager_->get_file_view(animation_id); diff --git a/td/telegram/BackgroundManager.cpp b/td/telegram/BackgroundManager.cpp index a266b7e06..f6603a995 100644 --- a/td/telegram/BackgroundManager.cpp +++ b/td/telegram/BackgroundManager.cpp @@ -472,9 +472,8 @@ Result BackgroundManager::get_background_url(const string &name, void BackgroundManager::reload_background_from_server( BackgroundId background_id, const string &background_name, telegram_api::object_ptr &&input_wallpaper, Promise &&promise) const { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + td_->create_handler(std::move(promise)) ->send(background_id, background_name, std::move(input_wallpaper)); } diff --git a/td/telegram/CallActor.cpp b/td/telegram/CallActor.cpp index 6ef03cfd7..259d00a45 100644 --- a/td/telegram/CallActor.cpp +++ b/td/telegram/CallActor.cpp @@ -840,7 +840,7 @@ void CallActor::send_with_promise(NetQueryPtr query, Promise promis void CallActor::hangup() { container_.for_each( - [](auto id, Promise &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); + [](auto id, Promise &promise) { promise.set_error(Global::request_aborted_error()); }); stop(); } diff --git a/td/telegram/CallbackQueriesManager.cpp b/td/telegram/CallbackQueriesManager.cpp index 69bc06e24..9b72b10cf 100644 --- a/td/telegram/CallbackQueriesManager.cpp +++ b/td/telegram/CallbackQueriesManager.cpp @@ -274,9 +274,7 @@ void CallbackQueriesManager::send_get_callback_answer_query( FullMessageId full_message_id, tl_object_ptr &&payload, tl_object_ptr &&password, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto dialog_id = full_message_id.get_dialog_id(); if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) { diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 555345681..cf85c2f7d 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -956,9 +956,7 @@ void ConfigManager::lazy_request_config() { } void ConfigManager::get_app_config(Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get(); if (auth_manager != nullptr && auth_manager->is_bot()) { @@ -974,9 +972,7 @@ void ConfigManager::get_app_config(Promise } void ConfigManager::get_content_settings(Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get(); if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) { @@ -991,9 +987,7 @@ void ConfigManager::get_content_settings(Promise &&promise) { } void ConfigManager::set_content_settings(bool ignore_sensitive_content_restrictions, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); last_set_content_settings_ = ignore_sensitive_content_restrictions; auto &queries = set_content_settings_queries_[ignore_sensitive_content_restrictions]; @@ -1011,9 +1005,7 @@ void ConfigManager::set_content_settings(bool ignore_sensitive_content_restricti } void ConfigManager::get_global_privacy_settings(Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get(); if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) { @@ -1028,9 +1020,8 @@ void ConfigManager::get_global_privacy_settings(Promise &&promise) { } void ConfigManager::set_archive_and_mute(bool archive_and_mute, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + if (archive_and_mute) { remove_suggested_action(suggested_actions_, SuggestedAction{SuggestedAction::Type::EnableArchiveAndMuteNewChats}); } diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 0d68259b8..78449fca0 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -1185,13 +1185,11 @@ class TogglePrehistoryHiddenQuery final : public Td::ResultHandler { td->updates_manager_->on_get_updates( std::move(ptr), - PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_, + PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_), + channel_id = channel_id_, is_all_history_available = is_all_history_available_](Unit result) mutable { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_is_all_history_available, - channel_id, is_all_history_available, std::move(promise)); + send_closure(actor_id, &ContactsManager::on_update_channel_is_all_history_available, channel_id, + is_all_history_available, std::move(promise)); })); } @@ -1417,13 +1415,11 @@ class ToggleSlowModeQuery final : public Td::ResultHandler { LOG(INFO) << "Receive result for ToggleSlowModeQuery: " << to_string(ptr); td->updates_manager_->on_get_updates( - std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_, - slow_mode_delay = slow_mode_delay_](Unit result) mutable { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_slow_mode_delay, channel_id, - slow_mode_delay, std::move(promise)); + std::move(ptr), + PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_), + channel_id = channel_id_, slow_mode_delay = slow_mode_delay_](Unit result) mutable { + send_closure(actor_id, &ContactsManager::on_update_channel_slow_mode_delay, channel_id, slow_mode_delay, + std::move(promise)); })); } @@ -5327,9 +5323,7 @@ void ContactsManager::reload_contacts(bool force) { } void ContactsManager::add_contact(Contact contact, bool share_phone_number, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); if (!are_contacts_loaded_) { load_contacts(PromiseCreator::lambda([actor_id = actor_id(this), contact = std::move(contact), share_phone_number, @@ -5475,11 +5469,12 @@ void ContactsManager::on_load_imported_contacts_from_database(string value) { LOG(INFO) << "Successfully loaded " << all_imported_contacts_.size() << " imported contacts from database"; } - load_imported_contact_users_multipromise_.add_promise(PromiseCreator::lambda([](Result<> result) { - if (result.is_ok()) { - send_closure_later(G()->contacts_manager(), &ContactsManager::on_load_imported_contacts_finished); - } - })); + load_imported_contact_users_multipromise_.add_promise( + PromiseCreator::lambda([actor_id = actor_id(this)](Result result) { + if (result.is_ok()) { + send_closure_later(actor_id, &ContactsManager::on_load_imported_contacts_finished); + } + })); auto lock_promise = load_imported_contact_users_multipromise_.get_promise(); @@ -5729,9 +5724,7 @@ std::pair> ContactsManager::search_contacts(const string & } void ContactsManager::share_phone_number(UserId user_id, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); if (!are_contacts_loaded_) { load_contacts(PromiseCreator::lambda( @@ -6185,7 +6178,8 @@ void ContactsManager::upload_profile_photo(FileId file_id, bool is_animation, do CHECK(uploaded_profile_photos_.find(file_id) == uploaded_profile_photos_.end()); uploaded_profile_photos_.emplace( file_id, UploadedProfilePhoto{main_frame_timestamp, is_animation, reupload_count, std::move(promise)}); - LOG(INFO) << "Ask to upload profile photo " << file_id << " with bad parts " << bad_parts; + LOG(INFO) << "Ask to upload " << (is_animation ? "animated" : "static") << " profile photo " << file_id + << " with bad parts " << bad_parts; // TODO use force_reupload if reupload_count >= 1, replace reupload_count with is_reupload td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_profile_photo_callback_, 32, 0); } @@ -6584,9 +6578,7 @@ void ContactsManager::get_channel_statistics_dc_id(DialogId dialog_id, bool for_ void ContactsManager::get_channel_statistics_dc_id_impl(ChannelId channel_id, bool for_full_statistics, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto channel_full = get_channel_full(channel_id, false, "get_channel_statistics_dc_id_impl"); if (channel_full == nullptr) { @@ -6615,9 +6607,8 @@ void ContactsManager::get_channel_statistics(DialogId dialog_id, bool is_dark, void ContactsManager::send_get_channel_stats_query(DcId dc_id, ChannelId channel_id, bool is_dark, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + const Channel *c = get_channel(channel_id); CHECK(c != nullptr); if (c->is_megagroup) { @@ -6666,9 +6657,7 @@ void ContactsManager::get_channel_message_statistics(FullMessageId full_message_ void ContactsManager::send_get_channel_message_stats_query( DcId dc_id, FullMessageId full_message_id, bool is_dark, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto dialog_id = full_message_id.get_dialog_id(); if (!td_->messages_manager_->have_message_force(full_message_id, "send_get_channel_message_stats_query")) { @@ -6697,9 +6686,7 @@ void ContactsManager::load_statistics_graph(DialogId dialog_id, const string &to void ContactsManager::send_load_async_graph_query(DcId dc_id, string token, int64 x, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); td_->create_handler(std::move(promise))->send(token, x, dc_id); } @@ -7218,9 +7205,7 @@ void ContactsManager::transfer_dialog_ownership(DialogId dialog_id, UserId user_ void ContactsManager::transfer_channel_ownership( ChannelId channel_id, UserId user_id, tl_object_ptr input_check_password, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); td_->create_handler(std::move(promise)) ->send(channel_id, user_id, std::move(input_check_password)); @@ -7285,10 +7270,7 @@ void ContactsManager::export_dialog_invite_link(DialogId dialog_id, int32 expire void ContactsManager::export_dialog_invite_link_impl(DialogId dialog_id, int32 expire_date, int32 usage_limit, bool is_permanent, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id)); td_->create_handler(std::move(promise)) @@ -7479,6 +7461,8 @@ void ContactsManager::delete_chat_participant(ChatId chat_id, UserId user_id, bo void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, DialogParticipantStatus status, DialogParticipantStatus old_status, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(INFO) << "Restrict " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to " << status; const Channel *c = get_channel(channel_id); @@ -7536,22 +7520,22 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogI if (old_status.is_member() && !status.is_member() && !status.is_banned()) { // we can't make participant Left without kicking it first - auto on_result_promise = PromiseCreator::lambda([channel_id, participant_dialog_id, status, - promise = std::move(promise)](Result<> result) mutable { + auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, participant_dialog_id, + status, promise = std::move(promise)](Result<> result) mutable { if (result.is_error()) { return promise.set_error(result.move_as_error()); } create_actor("RestrictChannelParticipantSleepActor", 1.0, - PromiseCreator::lambda([channel_id, participant_dialog_id, status, + PromiseCreator::lambda([actor_id, channel_id, participant_dialog_id, status, promise = std::move(promise)](Result<> result) mutable { if (result.is_error()) { return promise.set_error(result.move_as_error()); } - send_closure(G()->contacts_manager(), &ContactsManager::restrict_channel_participant, - channel_id, participant_dialog_id, status, - DialogParticipantStatus::Banned(0), std::move(promise)); + send_closure(actor_id, &ContactsManager::restrict_channel_participant, channel_id, + participant_dialog_id, status, DialogParticipantStatus::Banned(0), + std::move(promise)); })) .release(); }); @@ -7969,10 +7953,10 @@ void ContactsManager::on_load_contacts_from_database(string value) { LOG(INFO) << "Successfully loaded " << user_ids.size() << " contacts from database"; - load_contact_users_multipromise_.add_promise( - PromiseCreator::lambda([expected_contact_count = user_ids.size()](Result<> result) { + load_contact_users_multipromise_.add_promise(PromiseCreator::lambda( + [actor_id = actor_id(this), expected_contact_count = user_ids.size()](Result result) { if (result.is_ok()) { - send_closure(G()->contacts_manager(), &ContactsManager::on_get_contacts_finished, expected_contact_count); + send_closure(actor_id, &ContactsManager::on_get_contacts_finished, expected_contact_count); } })); @@ -9693,18 +9677,18 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo } } if (u->is_name_changed) { - td_->messages_manager_->on_dialog_title_updated(DialogId(user_id)); - for_each_secret_chat_with_user(user_id, - [messages_manager = td_->messages_manager_.get()](SecretChatId secret_chat_id) { - messages_manager->on_dialog_title_updated(DialogId(secret_chat_id)); - }); + auto messages_manager = td_->messages_manager_.get(); + messages_manager->on_dialog_title_updated(DialogId(user_id)); + for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) { + messages_manager->on_dialog_title_updated(DialogId(secret_chat_id)); + }); } if (u->is_photo_changed) { - td_->messages_manager_->on_dialog_photo_updated(DialogId(user_id)); - for_each_secret_chat_with_user(user_id, - [messages_manager = td_->messages_manager_.get()](SecretChatId secret_chat_id) { - messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id)); - }); + auto messages_manager = td_->messages_manager_.get(); + messages_manager->on_dialog_photo_updated(DialogId(user_id)); + for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) { + messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id)); + }); } if (u->is_status_changed && user_id != get_my_id()) { auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached(); @@ -10437,7 +10421,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c if (chat->groupcall_default_join_as_ != nullptr) { default_join_group_call_as_dialog_id = DialogId(chat->groupcall_default_join_as_); } - // use send closure later to not crete synchronously default_join_group_call_as_dialog_id + // use send closure later to not create synchronously default_join_group_call_as_dialog_id send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(chat_id), default_join_group_call_as_dialog_id, false); @@ -10653,7 +10637,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr &&c if (channel->groupcall_default_join_as_ != nullptr) { default_join_group_call_as_dialog_id = DialogId(channel->groupcall_default_join_as_); } - // use send closure later to not crete synchronously default_join_group_call_as_dialog_id + // use send closure later to not create synchronously default_join_group_call_as_dialog_id send_closure_later(G()->messages_manager(), &MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(channel_id), default_join_group_call_as_dialog_id, false); @@ -11701,9 +11685,7 @@ void ContactsManager::on_get_channel_participants( ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit, string additional_query, int32 additional_limit, tl_object_ptr &&channel_participants, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); on_get_users(std::move(channel_participants->users_), "on_get_channel_participants"); on_get_chats(std::move(channel_participants->chats_), "on_get_channel_participants"); @@ -13331,9 +13313,8 @@ void ContactsManager::on_update_channel_location(ChannelId channel_id, const Dia void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay"); if (channel_full != nullptr) { on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0); @@ -13380,9 +13361,7 @@ void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_f void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); CHECK(channel_id.is_valid()); auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_is_all_history_available"); if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) { @@ -14766,9 +14745,7 @@ void ContactsManager::get_dialog_participant(DialogId dialog_id, void ContactsManager::finish_get_dialog_participant(DialogParticipant &&dialog_participant, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto participant_dialog_id = dialog_participant.dialog_id; bool is_user = participant_dialog_id.get_type() == DialogType::User; @@ -14979,9 +14956,7 @@ void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promi void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); const auto *participant = get_chat_participant(chat_id, user_id); if (participant == nullptr) { @@ -15012,9 +14987,7 @@ void ContactsManager::search_chat_participants(ChatId chat_id, const string &que void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto chat_full = get_chat_full(chat_id); if (chat_full == nullptr) { @@ -15087,9 +15060,7 @@ void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId par void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); LOG(INFO) << "Receive a member " << dialog_participant.dialog_id << " of a channel " << channel_id; @@ -15218,8 +15189,9 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"}; load_users_multipromise.add_promise( - PromiseCreator::lambda([dialog_id, administrators, promise = std::move(promise)](Result<> result) mutable { - send_closure(G()->contacts_manager(), &ContactsManager::on_load_administrator_users_finished, dialog_id, + PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, administrators, + promise = std::move(promise)](Result result) mutable { + send_closure(actor_id, &ContactsManager::on_load_administrator_users_finished, dialog_id, std::move(administrators), std::move(result), std::move(promise)); })); @@ -15235,7 +15207,7 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id, vector administrators, Result<> result, Promise promise) { - if (result.is_ok()) { + if (!G()->close_flag() && result.is_ok()) { dialog_administrators_.emplace(dialog_id, std::move(administrators)); } promise.set_value(Unit()); @@ -15761,8 +15733,6 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co } void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr input_file) { - LOG(INFO) << "File " << file_id << " has been uploaded"; - auto it = uploaded_profile_photos_.find(file_id); CHECK(it != uploaded_profile_photos_.end()); @@ -15773,6 +15743,8 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptrset_error(Global::request_aborted_error()); send_closure(std::move(query.callback), &NetQueryCallback::on_result, std::move(query.net_query)); } parent_.reset(); diff --git a/td/telegram/DialogDb.cpp b/td/telegram/DialogDb.cpp index 2a28a195f..22a042f6f 100644 --- a/td/telegram/DialogDb.cpp +++ b/td/telegram/DialogDb.cpp @@ -288,8 +288,11 @@ class DialogDbImpl final : public DialogDbSyncInterface { return std::move(notification_groups); } - Status begin_transaction() final { - return db_.begin_transaction(); + Status begin_read_transaction() final { + return db_.begin_read_transaction(); + } + Status begin_write_transaction() final { + return db_.begin_write_transaction(); } Status commit_transaction() final { return db_.commit_transaction(); @@ -463,7 +466,7 @@ class DialogDbAsync final : public DialogDbAsyncInterface { if (pending_writes_.empty()) { return; } - sync_db_->begin_transaction().ensure(); + sync_db_->begin_write_transaction().ensure(); for (auto &query : pending_writes_) { query.set_value(Unit()); } diff --git a/td/telegram/DialogDb.h b/td/telegram/DialogDb.h index 5ed117355..37954ee41 100644 --- a/td/telegram/DialogDb.h +++ b/td/telegram/DialogDb.h @@ -55,7 +55,8 @@ class DialogDbSyncInterface { virtual Result get_secret_chat_count(FolderId folder_id) = 0; - virtual Status begin_transaction() = 0; + virtual Status begin_read_transaction() = 0; + virtual Status begin_write_transaction() = 0; virtual Status commit_transaction() = 0; }; diff --git a/td/telegram/FileReferenceManager.cpp b/td/telegram/FileReferenceManager.cpp index 573174178..a0bd73b69 100644 --- a/td/telegram/FileReferenceManager.cpp +++ b/td/telegram/FileReferenceManager.cpp @@ -227,28 +227,17 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source auto &node = nodes_[dest.node_id]; node.query->active_queries++; - auto promise = PromiseCreator::lambda([dest, file_source_id, file_reference_manager = G()->file_reference_manager(), - file_manager = G()->file_manager()](Result result) { - if (G()->close_flag()) { - VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing"; - return; - } - - auto new_promise = PromiseCreator::lambda([dest, file_source_id, file_reference_manager](Result result) { - if (G()->close_flag()) { - VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing"; - return; - } - + auto promise = PromiseCreator::lambda([dest, file_source_id, actor_id = actor_id(this), + file_manager_actor_id = G()->file_manager()](Result result) { + auto new_promise = PromiseCreator::lambda([dest, file_source_id, actor_id](Result result) { Status status; if (result.is_error()) { status = result.move_as_error(); } - send_closure(file_reference_manager, &FileReferenceManager::on_query_result, dest, file_source_id, - std::move(status), 0); + send_closure(actor_id, &FileReferenceManager::on_query_result, dest, file_source_id, std::move(status), 0); }); - send_closure(file_manager, &FileManager::on_file_reference_repaired, dest.node_id, file_source_id, + send_closure(file_manager_actor_id, &FileManager::on_file_reference_repaired, dest.node_id, file_source_id, std::move(result), std::move(new_promise)); }); auto index = static_cast(file_source_id.get()) - 1; @@ -272,7 +261,13 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source [&](const FileSourceWallpapers &source) { promise.set_error(Status::Error("Can't repair old wallpapers")); }, [&](const FileSourceWebPage &source) { send_closure_later(G()->web_pages_manager(), &WebPagesManager::reload_web_page_by_url, source.url, - std::move(promise)); + PromiseCreator::lambda([promise = std::move(promise)](Result &&result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(Unit()); + } + })); }, [&](const FileSourceSavedAnimations &source) { send_closure_later(G()->animations_manager(), &AnimationsManager::repair_saved_animations, std::move(promise)); @@ -300,6 +295,11 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source FileReferenceManager::Destination FileReferenceManager::on_query_result(Destination dest, FileSourceId file_source_id, Status status, int32 sub) { + if (G()->close_flag()) { + VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing"; + return dest; + } + VLOG(file_references) << "Receive result of file reference repair query for file " << dest.node_id << " with generation " << dest.generation << " from " << file_source_id << ": " << status << " " << sub; diff --git a/td/telegram/Global.h b/td/telegram/Global.h index 4248efb5b..ba0543d7a 100644 --- a/td/telegram/Global.h +++ b/td/telegram/Global.h @@ -383,6 +383,10 @@ class Global final : public ActorContext { #endif } + static Status request_aborted_error() { + return Status::Error(500, "Request aborted"); + } + void set_close_flag() { close_flag_ = true; } @@ -390,6 +394,10 @@ class Global final : public ActorContext { return close_flag_.load(); } + Status close_status() const { + return close_flag() ? request_aborted_error() : Status::OK(); + } + bool is_expected_error(const Status &error) const { CHECK(error.is_error()); if (error.code() == 401) { diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 56218b9ed..71f425016 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -1325,9 +1325,7 @@ void GroupCallManager::create_voice_chat(DialogId dialog_id, string title, int32 void GroupCallManager::on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); if (!input_group_call_id.is_valid()) { return promise.set_error(Status::Error(500, "Receive invalid group call identifier")); } @@ -1404,7 +1402,7 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i load_group_call_queries_.erase(it); if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); + result = Global::request_aborted_error(); } if (result.is_ok()) { @@ -2351,10 +2349,7 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, int32 channel_id, td_api::object_ptr quality, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -2441,10 +2436,7 @@ void GroupCallManager::finish_get_group_call_stream_segment(InputGroupCallId inp } void GroupCallManager::start_scheduled_group_call(GroupCallId group_call_id, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -2852,10 +2844,7 @@ void GroupCallManager::process_group_call_after_join_requests(InputGroupCallId i } void GroupCallManager::set_group_call_title(GroupCallId group_call_id, string title, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -2929,10 +2918,7 @@ void GroupCallManager::on_edit_group_call_title(InputGroupCallId input_group_cal void GroupCallManager::toggle_group_call_is_my_video_paused(GroupCallId group_call_id, bool is_my_video_paused, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3017,10 +3003,7 @@ void GroupCallManager::on_toggle_group_call_is_my_video_paused(InputGroupCallId void GroupCallManager::toggle_group_call_is_my_video_enabled(GroupCallId group_call_id, bool is_my_video_enabled, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3108,10 +3091,7 @@ void GroupCallManager::on_toggle_group_call_is_my_video_enabled(InputGroupCallId void GroupCallManager::toggle_group_call_is_my_presentation_paused(GroupCallId group_call_id, bool is_my_presentation_paused, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3199,10 +3179,7 @@ void GroupCallManager::on_toggle_group_call_is_my_presentation_paused(InputGroup void GroupCallManager::toggle_group_call_start_subscribed(GroupCallId group_call_id, bool start_subscribed, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3286,10 +3263,7 @@ void GroupCallManager::on_toggle_group_call_start_subscription(InputGroupCallId void GroupCallManager::toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3376,10 +3350,7 @@ void GroupCallManager::on_toggle_group_call_mute_new_participants(InputGroupCall } void GroupCallManager::revoke_group_call_invite_link(GroupCallId group_call_id, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3432,10 +3403,7 @@ void GroupCallManager::invite_group_call_participants(GroupCallId group_call_id, void GroupCallManager::get_group_call_invite_link(GroupCallId group_call_id, bool can_self_unmute, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3467,10 +3435,7 @@ void GroupCallManager::get_group_call_invite_link(GroupCallId group_call_id, boo void GroupCallManager::toggle_group_call_recording(GroupCallId group_call_id, bool is_enabled, string title, bool record_video, bool use_portrait_orientation, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3560,10 +3525,7 @@ void GroupCallManager::on_toggle_group_call_recording(InputGroupCallId input_gro void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_call_id, int32 audio_source, bool is_speaking, Promise &&promise, int32 date) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); auto *group_call = get_group_call(input_group_call_id); @@ -3609,9 +3571,6 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_ if (!is_recursive) { auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, audio_source, is_speaking, promise = std::move(promise), date](Result &&result) mutable { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } if (result.is_error()) { promise.set_value(Unit()); } else { diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 7e70cc82a..276ec31b2 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -1787,6 +1787,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise &promise) { resolve_recent_inline_bots_multipromise_.add_promise(std::move(promise)); if (recently_used_bots_loaded_ == 0) { resolve_recent_inline_bots_multipromise_.set_ignore_errors(true); + auto lock = resolve_recent_inline_bots_multipromise_.get_promise(); if (!G()->parameters().use_chat_info_db) { for (auto &bot_username : bot_usernames) { td_->messages_manager_->search_public_dialog(bot_username, false, @@ -1798,6 +1799,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise &promise) { td_->contacts_manager_->get_user(user_id, 3, resolve_recent_inline_bots_multipromise_.get_promise()); } } + lock.set_value(Unit()); recently_used_bots_loaded_ = 1; } return false; diff --git a/td/telegram/LanguagePackManager.cpp b/td/telegram/LanguagePackManager.cpp index 2e214185b..812070a1b 100644 --- a/td/telegram/LanguagePackManager.cpp +++ b/td/telegram/LanguagePackManager.cpp @@ -1313,7 +1313,7 @@ void LanguagePackManager::save_strings_to_database(SqliteKeyValue *kv, int32 new return; } - kv->begin_transaction().ensure(); + kv->begin_write_transaction().ensure(); for (auto str : strings) { if (!is_valid_key(str.first)) { LOG(ERROR) << "Have invalid key \"" << str.first << '"'; @@ -1873,7 +1873,7 @@ void LanguagePackManager::send_with_promise(NetQueryPtr query, Promise &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); + [](auto id, Promise &promise) { promise.set_error(Global::request_aborted_error()); }); stop(); } diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 03b89f97f..52df6bb85 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3987,16 +3987,16 @@ unique_ptr get_secret_message_content( } auto url = r_http_url.ok().get_url(); - auto web_page_id = td->web_pages_manager_->get_web_page_by_url(url, load_data_multipromise.get_promise()); - auto result = make_unique(FormattedText{std::move(message_text), std::move(entities)}, web_page_id); - if (!result->web_page_id.is_valid()) { - load_data_multipromise.add_promise( - PromiseCreator::lambda([td, url, &web_page_id = result->web_page_id](Result result) { - if (result.is_ok()) { - web_page_id = td->web_pages_manager_->get_web_page_by_url(url); - } - })); - } + auto result = make_unique(FormattedText{std::move(message_text), std::move(entities)}, WebPageId()); + td->web_pages_manager_->get_web_page_by_url( + url, + PromiseCreator::lambda([&web_page_id = result->web_page_id, promise = load_data_multipromise.get_promise()]( + Result r_web_page_id) mutable { + if (r_web_page_id.is_ok()) { + web_page_id = r_web_page_id.move_as_ok(); + } + promise.set_value(Unit()); + })); return std::move(result); } case secret_api::decryptedMessageMediaExternalDocument::ID: { diff --git a/td/telegram/MessagesDb.cpp b/td/telegram/MessagesDb.cpp index a02cb5490..f15dc3d3b 100644 --- a/td/telegram/MessagesDb.cpp +++ b/td/telegram/MessagesDb.cpp @@ -809,8 +809,8 @@ class MessagesDbImpl final : public MessagesDbSyncInterface { return std::move(result); } - Status begin_transaction() final { - return db_.begin_transaction(); + Status begin_write_transaction() final { + return db_.begin_write_transaction(); } Status commit_transaction() final { return db_.commit_transaction(); @@ -1176,7 +1176,7 @@ class MessagesDbAsync final : public MessagesDbAsyncInterface { if (pending_writes_.empty()) { return; } - sync_db_->begin_transaction().ensure(); + sync_db_->begin_write_transaction().ensure(); for (auto &query : pending_writes_) { query.set_value(Unit()); } diff --git a/td/telegram/MessagesDb.h b/td/telegram/MessagesDb.h index 34474b7fe..33abd123b 100644 --- a/td/telegram/MessagesDb.h +++ b/td/telegram/MessagesDb.h @@ -100,7 +100,7 @@ class MessagesDbSyncInterface { virtual Result get_calls(MessagesDbCallsQuery query) = 0; virtual Result get_messages_fts(MessagesDbFtsQuery query) = 0; - virtual Status begin_transaction() = 0; + virtual Status begin_write_transaction() = 0; virtual Status commit_transaction() = 0; }; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index daff9da7e..9f79837be 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -276,16 +276,9 @@ class GetDialogQuery final : public Td::ResultHandler { td->contacts_manager_->on_get_chats(std::move(result->chats_), "GetDialogQuery"); td->messages_manager_->on_get_dialogs( FolderId(), std::move(result->dialogs_), -1, std::move(result->messages_), - PromiseCreator::lambda([td = td, dialog_id = dialog_id_](Result<> result) { - if (G()->close_flag()) { - return; - } - if (result.is_ok()) { - td->messages_manager_->on_get_dialog_query_finished(dialog_id, Status::OK()); - } else { - td->messages_manager_->on_get_dialog_error(dialog_id, result.error(), "OnGetDialogs"); - td->messages_manager_->on_get_dialog_query_finished(dialog_id, result.move_as_error()); - } + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), dialog_id = dialog_id_](Result<> result) { + send_closure(actor_id, &MessagesManager::on_get_dialog_query_finished, dialog_id, + result.is_error() ? result.move_as_error() : Status::OK()); })); } @@ -454,12 +447,10 @@ class GetMessagesQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetMessagesQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetMessagesQuery"); LOG_IF(ERROR, info.is_channel_messages) << "Receive channel messages in GetMessagesQuery"; td->messages_manager_->on_get_messages(std::move(info.messages), info.is_channel_messages, false, - "GetMessagesQuery"); - - promise_.set_value(Unit()); + std::move(promise_), "GetMessagesQuery"); } void on_error(uint64 id, Status status) final { @@ -493,7 +484,7 @@ class GetChannelMessagesQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetChannelMessagesQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetChannelMessagesQuery"); LOG_IF(ERROR, !info.is_channel_messages) << "Receive ordinary messages in GetChannelMessagesQuery"; if (!td->auth_manager_->is_bot()) { // bots can receive messageEmpty because of their privacy mode vector empty_message_ids; @@ -509,20 +500,16 @@ class GetChannelMessagesQuery final : public Td::ResultHandler { } td->messages_manager_->get_channel_difference_if_needed( DialogId(channel_id_), std::move(info), - PromiseCreator::lambda( - [td = td, promise = std::move(promise_)](Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } - if (result.is_error()) { - promise.set_error(result.move_as_error()); - } else { - auto info = result.move_as_ok(); - td->messages_manager_->on_get_messages(std::move(info.messages), info.is_channel_messages, false, - "GetChannelMessagesQuery"); - promise.set_value(Unit()); - } - })); + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), + promise = std::move(promise_)](Result &&result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + auto info = result.move_as_ok(); + send_closure(actor_id, &MessagesManager::on_get_messages, std::move(info.messages), + info.is_channel_messages, false, std::move(promise), "GetChannelMessagesQuery"); + } + })); } void on_error(uint64 id, Status status) final { @@ -556,13 +543,11 @@ class GetScheduledMessagesQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetScheduledMessagesQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetScheduledMessagesQuery"); LOG_IF(ERROR, info.is_channel_messages != (dialog_id_.get_type() == DialogType::Channel)) << "Receive wrong messages constructor in GetScheduledMessagesQuery"; td->messages_manager_->on_get_messages(std::move(info.messages), info.is_channel_messages, true, - "GetScheduledMessagesQuery"); - - promise_.set_value(Unit()); + std::move(promise_), "GetScheduledMessagesQuery"); } void on_error(uint64 id, Status status) final { @@ -916,19 +901,18 @@ class GetCommonDialogsQuery final : public Td::ResultHandler { }; class GetBlockedDialogsQuery final : public Td::ResultHandler { - Promise promise_; + Promise> promise_; int32 offset_; int32 limit_; - int64 random_id_; public: - explicit GetBlockedDialogsQuery(Promise &&promise) : promise_(std::move(promise)) { + explicit GetBlockedDialogsQuery(Promise> &&promise) + : promise_(std::move(promise)) { } - void send(int32 offset, int32 limit, int64 random_id) { + void send(int32 offset, int32 limit) { offset_ = offset; limit_ = limit; - random_id_ = random_id; send_query(G()->net_query_creator().create(telegram_api::contacts_getBlocked(offset, limit))); } @@ -948,9 +932,9 @@ class GetBlockedDialogsQuery final : public Td::ResultHandler { td->contacts_manager_->on_get_users(std::move(blocked_peers->users_), "GetBlockedDialogsQuery"); td->contacts_manager_->on_get_chats(std::move(blocked_peers->chats_), "GetBlockedDialogsQuery"); - td->messages_manager_->on_get_blocked_dialogs(offset_, limit_, random_id_, + td->messages_manager_->on_get_blocked_dialogs(offset_, limit_, narrow_cast(blocked_peers->blocked_.size()), - std::move(blocked_peers->blocked_)); + std::move(blocked_peers->blocked_), std::move(promise_)); break; } case telegram_api::contacts_blockedSlice::ID: { @@ -958,19 +942,16 @@ class GetBlockedDialogsQuery final : public Td::ResultHandler { td->contacts_manager_->on_get_users(std::move(blocked_peers->users_), "GetBlockedDialogsQuery"); td->contacts_manager_->on_get_chats(std::move(blocked_peers->chats_), "GetBlockedDialogsQuery"); - td->messages_manager_->on_get_blocked_dialogs(offset_, limit_, random_id_, blocked_peers->count_, - std::move(blocked_peers->blocked_)); + td->messages_manager_->on_get_blocked_dialogs(offset_, limit_, blocked_peers->count_, + std::move(blocked_peers->blocked_), std::move(promise_)); break; } default: UNREACHABLE(); } - - promise_.set_value(Unit()); } void on_error(uint64 id, Status status) final { - td->messages_manager_->on_failed_get_blocked_dialogs(random_id_); promise_.set_error(std::move(status)); } }; @@ -1975,21 +1956,18 @@ class GetDialogMessageByDateQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetDialogMessageByDateQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetDialogMessageByDateQuery"); td->messages_manager_->get_channel_difference_if_needed( dialog_id_, std::move(info), - PromiseCreator::lambda([td = td, dialog_id = dialog_id_, date = date_, random_id = random_id_, + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), dialog_id = dialog_id_, date = date_, + random_id = random_id_, promise = std::move(promise_)](Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } if (result.is_error()) { promise.set_error(result.move_as_error()); } else { auto info = result.move_as_ok(); - td->messages_manager_->on_get_dialog_message_by_date_success(dialog_id, date, random_id, - std::move(info.messages)); - promise.set_value(Unit()); + send_closure(actor_id, &MessagesManager::on_get_dialog_message_by_date_success, dialog_id, date, random_id, + std::move(info.messages), std::move(promise)); } })); } @@ -2055,23 +2033,21 @@ class GetHistoryQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetHistoryQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetHistoryQuery"); td->messages_manager_->get_channel_difference_if_needed( dialog_id_, std::move(info), - PromiseCreator::lambda([td = td, dialog_id = dialog_id_, from_message_id = from_message_id_, - old_last_new_message_id = old_last_new_message_id_, offset = offset_, limit = limit_, - from_the_end = from_the_end_, + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), dialog_id = dialog_id_, + from_message_id = from_message_id_, old_last_new_message_id = old_last_new_message_id_, + offset = offset_, limit = limit_, from_the_end = from_the_end_, promise = std::move(promise_)](Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } if (result.is_error()) { promise.set_error(result.move_as_error()); } else { auto info = result.move_as_ok(); // TODO use info.total_count, info.pts - td->messages_manager_->on_get_history(dialog_id, from_message_id, old_last_new_message_id, offset, limit, - from_the_end, std::move(info.messages), std::move(promise)); + send_closure(actor_id, &MessagesManager::on_get_history, dialog_id, from_message_id, + old_last_new_message_id, offset, limit, from_the_end, std::move(info.messages), + std::move(promise)); } })); } @@ -2272,25 +2248,21 @@ class SearchMessagesQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "SearchMessagesQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "SearchMessagesQuery"); td->messages_manager_->get_channel_difference_if_needed( dialog_id_, std::move(info), - PromiseCreator::lambda([td = td, dialog_id = dialog_id_, query = std::move(query_), - sender_dialog_id = sender_dialog_id_, from_message_id = from_message_id_, - offset = offset_, limit = limit_, filter = filter_, + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), dialog_id = dialog_id_, + query = std::move(query_), sender_dialog_id = sender_dialog_id_, + from_message_id = from_message_id_, offset = offset_, limit = limit_, filter = filter_, top_thread_message_id = top_thread_message_id_, random_id = random_id_, promise = std::move(promise_)](Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } if (result.is_error()) { promise.set_error(result.move_as_error()); } else { auto info = result.move_as_ok(); - td->messages_manager_->on_get_dialog_messages_search_result( - dialog_id, query, sender_dialog_id, from_message_id, offset, limit, filter, top_thread_message_id, - random_id, info.total_count, std::move(info.messages)); - promise.set_value(Unit()); + send_closure(actor_id, &MessagesManager::on_get_dialog_messages_search_result, dialog_id, query, + sender_dialog_id, from_message_id, offset, limit, filter, top_thread_message_id, random_id, + info.total_count, std::move(info.messages), std::move(promise)); } })); } @@ -2400,25 +2372,21 @@ class SearchMessagesGlobalQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "SearchMessagesGlobalQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "SearchMessagesGlobalQuery"); td->messages_manager_->get_channel_differences_if_needed( std::move(info), - PromiseCreator::lambda([td = td, query = std::move(query_), offset_date = offset_date_, - offset_dialog_id = offset_dialog_id_, offset_message_id = offset_message_id_, - limit = limit_, filter = std::move(filter_), min_date = min_date_, max_date = max_date_, - random_id = random_id_, + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), query = std::move(query_), + offset_date = offset_date_, offset_dialog_id = offset_dialog_id_, + offset_message_id = offset_message_id_, limit = limit_, filter = std::move(filter_), + min_date = min_date_, max_date = max_date_, random_id = random_id_, promise = std::move(promise_)](Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } if (result.is_error()) { promise.set_error(result.move_as_error()); } else { auto info = result.move_as_ok(); - td->messages_manager_->on_get_messages_search_result(query, offset_date, offset_dialog_id, - offset_message_id, limit, filter, min_date, max_date, - random_id, info.total_count, std::move(info.messages)); - promise.set_value(Unit()); + send_closure(actor_id, &MessagesManager::on_get_messages_search_result, query, offset_date, + offset_dialog_id, offset_message_id, limit, filter, min_date, max_date, random_id, + info.total_count, std::move(info.messages), std::move(promise)); } })); } @@ -2458,7 +2426,7 @@ class GetAllScheduledMessagesQuery final : public Td::ResultHandler { if (result_ptr.ok()->get_id() == telegram_api::messages_messagesNotModified::ID) { td->messages_manager_->on_get_scheduled_server_messages(dialog_id_, generation_, Auto(), true); } else { - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetAllScheduledMessagesQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetAllScheduledMessagesQuery"); td->messages_manager_->on_get_scheduled_server_messages(dialog_id_, generation_, std::move(info.messages), false); } @@ -2500,20 +2468,17 @@ class GetRecentLocationsQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetRecentLocationsQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetRecentLocationsQuery"); td->messages_manager_->get_channel_difference_if_needed( dialog_id_, std::move(info), - PromiseCreator::lambda([td = td, dialog_id = dialog_id_, limit = limit_, + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), dialog_id = dialog_id_, limit = limit_, promise = std::move(promise_)](Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } if (result.is_error()) { promise.set_error(result.move_as_error()); } else { auto info = result.move_as_ok(); - td->messages_manager_->on_get_recent_locations(dialog_id, limit, info.total_count, std::move(info.messages), - std::move(promise)); + send_closure(actor_id, &MessagesManager::on_get_recent_locations, dialog_id, limit, info.total_count, + std::move(info.messages), std::move(promise)); } })); } @@ -2556,19 +2521,17 @@ class GetMessagePublicForwardsQuery final : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto info = td->messages_manager_->on_get_messages(result_ptr.move_as_ok(), "GetMessagePublicForwardsQuery"); + auto info = td->messages_manager_->get_messages_info(result_ptr.move_as_ok(), "GetMessagePublicForwardsQuery"); td->messages_manager_->get_channel_differences_if_needed( - std::move(info), PromiseCreator::lambda([td = td, promise = std::move(promise_)]( - Result &&result) mutable { - if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); - } + std::move(info), + PromiseCreator::lambda([actor_id = td->messages_manager_actor_.get(), + promise = std::move(promise_)](Result &&result) mutable { if (result.is_error()) { promise.set_error(result.move_as_error()); } else { auto info = result.move_as_ok(); - td->messages_manager_->on_get_message_public_forwards(info.total_count, std::move(info.messages), - std::move(promise)); + send_closure(actor_id, &MessagesManager::on_get_message_public_forwards, info.total_count, + std::move(info.messages), std::move(promise)); } })); } @@ -6254,8 +6217,6 @@ void MessagesManager::memory_stats(vector &output) { output.push_back(","); output.push_back("\"dialogs_\":"); output.push_back(std::to_string(this->dialogs_.size())); output.push_back(","); - output.push_back("\"found_blocked_dialogs_\":"); output.push_back(std::to_string(this->found_blocked_dialogs_.size())); - output.push_back(","); output.push_back("\"found_call_messages_\":"); output.push_back(std::to_string(this->found_call_messages_.size())); output.push_back(","); output.push_back("\"found_common_dialogs_\":"); output.push_back(std::to_string(this->found_common_dialogs_.size())); @@ -8228,6 +8189,10 @@ void MessagesManager::repair_dialog_active_group_call_id(DialogId dialog_id) { } void MessagesManager::do_repair_dialog_active_group_call_id(DialogId dialog_id) { + if (G()->close_flag()) { + return; + } + Dialog *d = get_dialog(dialog_id); CHECK(d != nullptr); bool need_repair_active_group_call_id = d->has_active_group_call && !d->active_group_call_id.is_valid(); @@ -9198,19 +9163,15 @@ void MessagesManager::after_get_difference() { dump_debug_message_op(get_dialog(dialog_id)); } if (message_id <= d->last_new_message_id) { - get_message_from_server( - it.first, PromiseCreator::lambda([this, full_message_id](Result result) { - if (G()->close_flag()) { - return; - } - if (result.is_error()) { - LOG(WARNING) << "Failed to get missing " << full_message_id << ": " << result.error(); - } else { - LOG(WARNING) << "Successfully get missing " << full_message_id << ": " - << to_string(get_message_object(full_message_id, "after_get_difference")); - } - }), - "get missing"); + get_message_from_server(it.first, PromiseCreator::lambda([full_message_id](Result result) { + if (result.is_error()) { + LOG(WARNING) + << "Failed to get missing " << full_message_id << ": " << result.error(); + } else { + LOG(WARNING) << "Successfully get missing " << full_message_id; + } + }), + "get missing"); } else if (dialog_id.get_type() == DialogType::Channel) { LOG(INFO) << "Schedule getDifference in " << dialog_id.get_channel_id(); channel_get_difference_retry_timeout_.add_timeout_in(dialog_id.get(), 0.001); @@ -9254,7 +9215,7 @@ void MessagesManager::on_get_empty_messages(DialogId dialog_id, vector &&messages_ptr, const char *source) { CHECK(messages_ptr != nullptr); LOG(DEBUG) << "Receive result for " << source << ": " << to_string(messages_ptr); @@ -9334,27 +9295,27 @@ void MessagesManager::get_channel_differences_if_needed(MessagesInfo &&messages_ } } // must be added after messages_info is checked - mpas.add_promise(PromiseCreator::lambda( - [messages_info = std::move(messages_info), promise = std::move(promise)](Unit ignored) mutable { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - promise.set_value(std::move(messages_info)); - })); + mpas.add_promise(PromiseCreator::lambda([messages_info = std::move(messages_info), promise = std::move(promise)]( + Unit ignored) mutable { promise.set_value(std::move(messages_info)); })); lock.set_value(Unit()); } void MessagesManager::on_get_messages(vector> &&messages, bool is_channel_message, - bool is_scheduled, const char *source) { + bool is_scheduled, Promise &&promise, const char *source) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(DEBUG) << "Receive " << messages.size() << " messages"; for (auto &message : messages) { on_get_message(std::move(message), false, is_channel_message, is_scheduled, false, false, source); } + promise.set_value(Unit()); } void MessagesManager::on_get_history(DialogId dialog_id, MessageId from_message_id, MessageId old_last_new_message_id, int32 offset, int32 limit, bool from_the_end, vector> &&messages, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(INFO) << "Receive " << messages.size() << " history messages " << (from_the_end ? "from the end " : "") << "in " << dialog_id << " from " << from_message_id << " with offset " << offset << " and limit " << limit; CHECK(-limit < offset && offset <= 0); @@ -9699,15 +9660,11 @@ void MessagesManager::on_failed_public_dialogs_search(const string &query, Statu } } -void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, - DialogId sender_dialog_id, MessageId from_message_id, - int32 offset, int32 limit, MessageSearchFilter filter, - MessageId top_thread_message_id, int64 random_id, - int32 total_count, - vector> &&messages) { - if (G()->close_flag()) { - return; - } +void MessagesManager::on_get_dialog_messages_search_result( + DialogId dialog_id, const string &query, DialogId sender_dialog_id, MessageId from_message_id, int32 offset, + int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 random_id, int32 total_count, + vector> &&messages, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); LOG(INFO) << "Receive " << messages.size() << " found messages in " << dialog_id; if (!dialog_id.is_valid()) { @@ -9771,6 +9728,7 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c } } it->second.first = total_count; + promise.set_value(Unit()); return; } @@ -9868,6 +9826,7 @@ void MessagesManager::on_get_dialog_messages_search_result(DialogId dialog_id, c } it->second.first = total_count; + promise.set_value(Unit()); } void MessagesManager::on_failed_dialog_messages_search(DialogId dialog_id, int64 random_id) { @@ -9920,7 +9879,10 @@ void MessagesManager::on_get_messages_search_result(const string &query, int32 o MessageId offset_message_id, int32 limit, MessageSearchFilter filter, int32 min_date, int32 max_date, int64 random_id, int32 total_count, - vector> &&messages) { + vector> &&messages, + Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(INFO) << "Receive " << messages.size() << " found messages"; auto it = found_messages_.find(random_id); CHECK(it != found_messages_.end()); @@ -9944,6 +9906,7 @@ void MessagesManager::on_get_messages_search_result(const string &query, int32 o total_count = static_cast(result.size()); } it->second.first = total_count; + promise.set_value(Unit()); } void MessagesManager::on_failed_messages_search(int64 random_id) { @@ -10013,6 +9976,8 @@ void MessagesManager::on_get_scheduled_server_messages(DialogId dialog_id, uint3 void MessagesManager::on_get_recent_locations(DialogId dialog_id, int32 limit, int32 total_count, vector> &&messages, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(INFO) << "Receive " << messages.size() << " recent locations in " << dialog_id; vector result; for (auto &message : messages) { @@ -10049,9 +10014,8 @@ void MessagesManager::on_get_recent_locations(DialogId dialog_id, int32 limit, i void MessagesManager::on_get_message_public_forwards(int32 total_count, vector> &&messages, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(INFO) << "Receive " << messages.size() << " forwarded messages"; vector> result; FullMessageId last_full_message_id; @@ -10392,9 +10356,7 @@ bool MessagesManager::can_revoke_message(DialogId dialog_id, const Message *m) c void MessagesManager::delete_messages(DialogId dialog_id, const vector &input_message_ids, bool revoke, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); Dialog *d = get_dialog_force(dialog_id, "delete_messages"); if (d == nullptr) { return promise.set_error(Status::Error(400, "Chat is not found")); @@ -11611,6 +11573,7 @@ void MessagesManager::repair_server_dialog_total_count(DialogListId dialog_list_ return; } + LOG(INFO) << "Repair total chat count in " << dialog_list_id; send_closure(td_->create_net_actor(Promise()), &GetDialogListActor::send, dialog_list_id.get_folder_id(), 2147483647, ServerMessageId(), DialogId(), 1, get_sequence_dispatcher_id(DialogId(), MessageContentType::None)); @@ -11681,15 +11644,15 @@ void MessagesManager::on_get_secret_chat_total_count(DialogListId dialog_list_id } } -void MessagesManager::recalc_unread_count(DialogListId dialog_list_id, int32 old_dialog_total_count) { - if (td_->auth_manager_->is_bot() || !G()->parameters().use_message_db) { +void MessagesManager::recalc_unread_count(DialogListId dialog_list_id, int32 old_dialog_total_count, bool force) { + if (G()->close_flag() || td_->auth_manager_->is_bot() || !G()->parameters().use_message_db) { return; } auto *list_ptr = get_dialog_list(dialog_list_id); CHECK(list_ptr != nullptr); auto &list = *list_ptr; - if (!list.need_unread_count_recalc_) { + if (!list.need_unread_count_recalc_ && !force) { return; } LOG(INFO) << "Recalculate unread counts in " << dialog_list_id; @@ -11765,7 +11728,10 @@ void MessagesManager::recalc_unread_count(DialogListId dialog_list_id, int32 old need_save = true; } } else { - repair_server_dialog_total_count(dialog_list_id); + if (list.server_dialog_total_count_ == -1) { + // recalc_unread_count is called only after getDialogs request; it is unneeded to call getDialogs again + repair_server_dialog_total_count(dialog_list_id); + } if (list.secret_chat_total_count_ == -1) { repair_secret_chat_total_count(dialog_list_id); @@ -13233,12 +13199,9 @@ void MessagesManager::add_secret_message(unique_ptr pendin multipromise.set_ignore_errors(true); int64 token = pending_secret_messages_.add(std::move(pending_secret_message)); - multipromise.add_promise(PromiseCreator::lambda([token, actor_id = actor_id(this), - this](Result result) mutable { - if (result.is_ok() && !G()->close_flag()) { // if we aren't closing - this->pending_secret_messages_.finish(token, [actor_id](unique_ptr pending_secret_message) { - send_closure_later(actor_id, &MessagesManager::finish_add_secret_message, std::move(pending_secret_message)); - }); + multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), token](Result result) { + if (result.is_ok()) { + send_closure(actor_id, &MessagesManager::on_add_secret_message_ready, token); } })); @@ -13248,6 +13211,17 @@ void MessagesManager::add_secret_message(unique_ptr pendin lock_promise.set_value(Unit()); } +void MessagesManager::on_add_secret_message_ready(int64 token) { + if (G()->close_flag()) { + return; + } + + pending_secret_messages_.finish( + token, [actor_id = actor_id(this)](unique_ptr pending_secret_message) { + send_closure_later(actor_id, &MessagesManager::finish_add_secret_message, std::move(pending_secret_message)); + }); +} + void MessagesManager::finish_add_secret_message(unique_ptr pending_secret_message) { if (G()->close_flag()) { return; @@ -14439,7 +14413,13 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector full_message_id_to_dialog_date; std::unordered_map, FullMessageIdHash> full_message_id_to_message; for (auto &message : messages) { @@ -14513,8 +14493,6 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorlast_server_dialog_date_ == MIN_DIALOG_DATE; if (from_dialog_list && total_count < narrow_cast(dialogs.size())) { LOG(ERROR) << "Receive chat total_count = " << total_count << ", but " << dialogs.size() << " chats"; total_count = narrow_cast(dialogs.size()); @@ -14734,28 +14712,6 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vectorlast_server_dialog_date_ < max_dialog_date) { folder->last_server_dialog_date_ = max_dialog_date; update_last_dialog_date(folder_id); - - if (max_dialog_date != MAX_DIALOG_DATE) { - bool need_new_get_dialog_list = false; - for (const auto &list_it : dialog_lists_) { - auto &dialog_list = list_it.second; - if (!dialog_list.load_list_queries_.empty() && has_dialogs_from_folder(dialog_list, *folder)) { - LOG(INFO) << "Need to load more chats in " << folder_id << " for " << list_it.first; - need_new_get_dialog_list = true; - } - } - if (need_new_get_dialog_list) { - LOG(INFO) << "Schedule chats list load in " << folder_id; - auto &multipromise = folder->load_folder_dialog_list_multipromise_; - multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), folder_id](Result result) { - if (result.is_ok()) { - LOG(INFO) << "Continue to load chat list in " << folder_id; - send_closure_later(actor_id, &MessagesManager::load_folder_dialog_list, folder_id, int32{MAX_GET_DIALOGS}, - false); - } - })); - } - } } else if (promise) { LOG(ERROR) << "Last server dialog date didn't increased from " << folder->last_server_dialog_date_ << " to " << max_dialog_date << " after receiving " << dialogs.size() << " chats " << added_dialog_ids @@ -14819,10 +14775,6 @@ void MessagesManager::on_get_dialogs(FolderId folder_id, vector &&result, vector &&filters, Promise> &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); if (result.is_error()) { return promise.set_error(result.move_as_error()); } @@ -15825,6 +15778,9 @@ vector MessagesManager::get_dialogs(DialogListId dialog_list_id, Dialo promise.set_value(Unit()); return result; } else { + if (!result.empty()) { + LOG(INFO) << "Have only " << result.size() << " chats, but " << limit << " chats more are needed"; + } load_dialog_list(list, limit, std::move(promise)); return {}; } @@ -15844,6 +15800,7 @@ void MessagesManager::load_dialog_list(DialogList &list, int32 limit, Promiseclose_flag()) { + return; + } + CHECK(!td_->auth_manager_->is_bot()); auto &folder = *get_dialog_folder(folder_id); if (folder.folder_last_dialog_date_ == MAX_DIALOG_DATE) { @@ -15865,19 +15826,19 @@ void MessagesManager::load_folder_dialog_list(FolderId folder_id, int32 limit, b return; } - LOG(INFO) << "Load dialog list in " << folder_id << " with limit " << limit; auto &multipromise = folder.load_folder_dialog_list_multipromise_; if (multipromise.promise_count() != 0) { // queries have already been sent, just wait for the result + LOG(INFO) << "Skip loading of dialog list in " << folder_id << " with limit " << limit + << ", because it is already being loaded"; if (use_database && folder.load_dialog_list_limit_max_ != 0) { folder.load_dialog_list_limit_max_ = max(folder.load_dialog_list_limit_max_, limit); } return; } + LOG(INFO) << "Load dialog list in " << folder_id << " with limit " << limit; multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), folder_id](Result result) { - if (result.is_error() && !G()->close_flag()) { - send_closure(actor_id, &MessagesManager::on_load_folder_dialog_list_fail, folder_id, result.move_as_error()); - } + send_closure_later(actor_id, &MessagesManager::on_load_folder_dialog_list, folder_id, std::move(result)); })); bool is_query_sent = false; @@ -15888,7 +15849,7 @@ void MessagesManager::load_folder_dialog_list(FolderId folder_id, int32 limit, b LOG(INFO) << "Get chats from " << folder.last_server_dialog_date_; multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), folder_id](Result result) { if (result.is_ok()) { - send_closure(actor_id, &MessagesManager::recalc_unread_count, DialogListId(folder_id), -1); + send_closure(actor_id, &MessagesManager::recalc_unread_count, DialogListId(folder_id), -1, true); } })); auto lock = multipromise.get_promise(); @@ -15911,10 +15872,34 @@ void MessagesManager::load_folder_dialog_list(FolderId folder_id, int32 limit, b CHECK(is_query_sent); } -void MessagesManager::on_load_folder_dialog_list_fail(FolderId folder_id, Status error) { - LOG(WARNING) << "Failed to load chats in " << folder_id << ": " << error; +void MessagesManager::on_load_folder_dialog_list(FolderId folder_id, Result &&result) { + if (G()->close_flag()) { + return; + } CHECK(!td_->auth_manager_->is_bot()); + const auto &folder = *get_dialog_folder(folder_id); + if (result.is_ok()) { + LOG(INFO) << "Successfully loaded chats in " << folder_id; + if (folder.last_server_dialog_date_ == MAX_DIALOG_DATE) { + return; + } + + bool need_new_get_dialog_list = false; + for (const auto &list_it : dialog_lists_) { + auto &list = list_it.second; + if (!list.load_list_queries_.empty() && has_dialogs_from_folder(list, folder)) { + LOG(INFO) << "Need to load more chats in " << folder_id << " for " << list_it.first; + need_new_get_dialog_list = true; + } + } + if (need_new_get_dialog_list) { + load_folder_dialog_list(folder_id, int32{MAX_GET_DIALOGS}, false); + } + return; + } + + LOG(WARNING) << "Failed to load chats in " << folder_id << ": " << result.error(); vector> promises; for (auto &list_it : dialog_lists_) { auto &list = list_it.second; @@ -15925,7 +15910,7 @@ void MessagesManager::on_load_folder_dialog_list_fail(FolderId folder_id, Status } for (auto &promise : promises) { - promise.set_error(error.clone()); + promise.set_error(result.error().clone()); } } @@ -15950,9 +15935,7 @@ void MessagesManager::load_folder_dialog_list_from_database(FolderId folder_id, void MessagesManager::on_get_dialogs_from_database(FolderId folder_id, int32 limit, DialogDbGetDialogsResult &&dialogs, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); CHECK(!td_->auth_manager_->is_bot()); auto &folder = *get_dialog_folder(folder_id); LOG(INFO) << "Receive " << dialogs.dialogs.size() << " from expected " << limit << " chats in " << folder_id @@ -16040,7 +16023,7 @@ void MessagesManager::preload_folder_dialog_list(FolderId folder_id) { // otherwise load more dialogs from the server load_folder_dialog_list(folder_id, MAX_GET_DIALOGS, false); } else { - recalc_unread_count(DialogListId(folder_id)); + recalc_unread_count(DialogListId(folder_id), -1, false); } } @@ -16070,12 +16053,14 @@ void MessagesManager::get_dialogs_from_list_impl(int64 task_id) { CHECK(task_it != get_dialogs_tasks_.end()); auto &task = task_it->second; auto promise = PromiseCreator::lambda([actor_id = actor_id(this), task_id](Result &&result) { + // on_get_dialogs_from_list can delete get_dialogs_tasks_[task_id], so it must be called later send_closure_later(actor_id, &MessagesManager::on_get_dialogs_from_list, task_id, std::move(result)); }); auto dialog_ids = get_dialogs(task.dialog_list_id, MIN_DIALOG_DATE, task.limit, true, false, std::move(promise)); auto &list = *get_dialog_list(task.dialog_list_id); auto total_count = get_dialog_total_count(list); - LOG(INFO) << "Receive " << dialog_ids.size() << " chats out of " << total_count << "/" << task.limit; + LOG(INFO) << "Receive " << dialog_ids.size() << " chats instead of " << task.limit << " out of " << total_count + << " in " << task.dialog_list_id; CHECK(dialog_ids.size() <= static_cast(total_count)); CHECK(dialog_ids.size() <= static_cast(task.limit)); if (dialog_ids.size() == static_cast(min(total_count, task.limit)) || @@ -16093,11 +16078,13 @@ void MessagesManager::get_dialogs_from_list_impl(int64 task_id) { void MessagesManager::on_get_dialogs_from_list(int64 task_id, Result &&result) { auto task_it = get_dialogs_tasks_.find(task_id); if (task_it == get_dialogs_tasks_.end()) { - // the task has already been completed successfully + // the task has already been completed + LOG(INFO) << "Chat list load task " << task_id << " has already been completed"; return; } auto &task = task_it->second; if (result.is_error()) { + LOG(INFO) << "Chat list load task " << task_id << " failed with the error " << result.error(); auto task_promise = std::move(task.promise); get_dialogs_tasks_.erase(task_it); return task_promise.set_error(result.move_as_error()); @@ -16135,13 +16122,9 @@ vector MessagesManager::get_pinned_dialog_ids(DialogListId dialog_list } void MessagesManager::reload_pinned_dialogs(DialogListId dialog_list_id, Promise &&promise) { - if (td_->auth_manager_->is_bot()) { - // just in case - return promise.set_error(Status::Error(500, "Request aborted")); - } - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + CHECK(!td_->auth_manager_->is_bot()); + if (dialog_list_id.is_folder()) { send_closure(td_->create_net_actor(std::move(promise)), &GetPinnedDialogsActor::send, dialog_list_id.get_folder_id(), get_sequence_dispatcher_id(DialogId(), MessageContentType::None)); @@ -16500,6 +16483,7 @@ std::pair> MessagesManager::search_dialogs(const string } std::pair> MessagesManager::get_recently_opened_dialogs(int32 limit, Promise &&promise) { + CHECK(!td_->auth_manager_->is_bot()); return recently_opened_dialogs_.get_dialogs(limit, std::move(promise)); } @@ -16844,78 +16828,54 @@ void MessagesManager::block_message_sender_from_replies_on_server(MessageId mess ->send(message_id, delete_message, delete_all_messages, report_spam); } -std::pair> MessagesManager::get_blocked_dialogs(int32 offset, int32 limit, int64 &random_id, - Promise &&promise) { - LOG(INFO) << "Get blocked chats with offset = " << offset << " and limit = " << limit; - - if (random_id != 0) { - // request has already been sent before - auto it = found_blocked_dialogs_.find(random_id); - CHECK(it != found_blocked_dialogs_.end()); - auto result = std::move(it->second); - found_blocked_dialogs_.erase(it); - - promise.set_value(Unit()); - return result; - } - +void MessagesManager::get_blocked_dialogs(int32 offset, int32 limit, + Promise> &&promise) { if (offset < 0) { - promise.set_error(Status::Error(400, "Parameter offset must be non-negative")); - return {}; + return promise.set_error(Status::Error(400, "Parameter offset must be non-negative")); } if (limit <= 0) { - promise.set_error(Status::Error(400, "Parameter limit must be positive")); - return {}; + return promise.set_error(Status::Error(400, "Parameter limit must be positive")); } - do { - random_id = Random::secure_int64(); - } while (random_id == 0 || found_blocked_dialogs_.find(random_id) != found_blocked_dialogs_.end()); - found_blocked_dialogs_[random_id]; // reserve place for result - - td_->create_handler(std::move(promise))->send(offset, limit, random_id); - return {}; + td_->create_handler(std::move(promise))->send(offset, limit); } -void MessagesManager::on_get_blocked_dialogs(int32 offset, int32 limit, int64 random_id, int32 total_count, - vector> &&blocked_peers) { +void MessagesManager::on_get_blocked_dialogs(int32 offset, int32 limit, int32 total_count, + vector> &&blocked_peers, + Promise> &&promise) { LOG(INFO) << "Receive " << blocked_peers.size() << " blocked chats from offset " << offset << " out of " << total_count; - auto it = found_blocked_dialogs_.find(random_id); - CHECK(it != found_blocked_dialogs_.end()); - - auto &result = it->second.second; - CHECK(result.empty()); + vector dialog_ids; for (auto &blocked_peer : blocked_peers) { CHECK(blocked_peer != nullptr); DialogId dialog_id(blocked_peer->peer_id_); if (dialog_id.get_type() == DialogType::User) { if (td_->contacts_manager_->have_user(dialog_id.get_user_id())) { - result.push_back(dialog_id); + dialog_ids.push_back(dialog_id); } else { LOG(ERROR) << "Have no info about " << dialog_id.get_user_id(); } } else { - force_create_dialog(dialog_id, "on_get_blocked_dialogs"); - if (have_dialog(dialog_id)) { - result.push_back(dialog_id); + if (have_dialog_info(dialog_id)) { + force_create_dialog(dialog_id, "on_get_blocked_dialogs"); + if (have_dialog(dialog_id)) { + dialog_ids.push_back(dialog_id); + } } else { LOG(ERROR) << "Have no info about " << dialog_id; } } } - if (!result.empty() && offset + result.size() > static_cast(total_count)) { - LOG(ERROR) << "Fix total count of blocked chats from " << total_count << " to " << offset + result.size(); - total_count = offset + narrow_cast(result.size()); + if (!dialog_ids.empty() && offset + dialog_ids.size() > static_cast(total_count)) { + LOG(ERROR) << "Fix total count of blocked chats from " << total_count << " to " << offset + dialog_ids.size(); + total_count = offset + narrow_cast(dialog_ids.size()); } - it->second.first = total_count; -} -void MessagesManager::on_failed_get_blocked_dialogs(int64 random_id) { - auto it = found_blocked_dialogs_.find(random_id); - CHECK(it != found_blocked_dialogs_.end()); - found_blocked_dialogs_.erase(it); + auto senders = transform(dialog_ids, [this](DialogId dialog_id) { + return get_message_sender_object(dialog_id, "on_get_blocked_dialogs"); + }); + promise.set_value(td_api::make_object(total_count, std::move(senders))); } bool MessagesManager::have_message_force(FullMessageId full_message_id, const char *source) { @@ -17153,9 +17113,7 @@ void MessagesManager::process_discussion_message_impl( telegram_api::object_ptr &&result, DialogId dialog_id, MessageId message_id, DialogId expected_dialog_id, MessageId expected_message_id, Promise promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); MessageId max_message_id; MessageId last_read_inbox_message_id; @@ -17202,9 +17160,8 @@ void MessagesManager::process_discussion_message_impl( void MessagesManager::on_get_discussion_message(DialogId dialog_id, MessageId message_id, MessageThreadInfo &&message_thread_info, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + Dialog *d = get_dialog_force(dialog_id, "on_get_discussion_message"); CHECK(d != nullptr); @@ -17443,6 +17400,10 @@ void MessagesManager::get_dialog_info_full(DialogId dialog_id, Promise &&p } void MessagesManager::reload_dialog_info_full(DialogId dialog_id) { + if (G()->close_flag()) { + return; + } + switch (dialog_id.get_type()) { case DialogType::User: send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user_full, dialog_id.get_user_id()); @@ -17552,9 +17513,8 @@ void MessagesManager::get_message_from_server(FullMessageId full_message_id, Pro void MessagesManager::get_messages_from_server(vector &&message_ids, Promise &&promise, const char *source, tl_object_ptr input_message) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + if (message_ids.empty()) { LOG(ERROR) << "Empty message_ids from " << source; return promise.set_error(Status::Error(500, "There are no messages specified to fetch")); @@ -17890,6 +17850,8 @@ void MessagesManager::get_message_link_info(Slice url, Promise } void MessagesManager::on_get_message_link_dialog(MessageLinkInfo &&info, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + DialogId dialog_id; if (info.username.empty()) { if (!td_->contacts_manager_->have_channel(info.channel_id)) { @@ -17922,6 +17884,8 @@ void MessagesManager::on_get_message_link_dialog(MessageLinkInfo &&info, Promise void MessagesManager::on_get_message_link_message(MessageLinkInfo &&info, DialogId dialog_id, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + Message *m = get_message_force({dialog_id, info.message_id}, "on_get_message_link_message"); if (info.comment_message_id == MessageId() || m == nullptr || !is_broadcast_channel(dialog_id) || !m->reply_info.is_comment || !is_active_message_reply_info(dialog_id, m->reply_info)) { @@ -17949,6 +17913,8 @@ void MessagesManager::on_get_message_link_message(MessageLinkInfo &&info, Dialog void MessagesManager::on_get_message_link_discussion_message(MessageLinkInfo &&info, DialogId comment_dialog_id, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + CHECK(comment_dialog_id.is_valid()); info.comment_dialog_id = comment_dialog_id; @@ -18590,8 +18556,11 @@ void MessagesManager::edit_dialog_filter(unique_ptr new_dialog_fil get_dialogs_from_list(dialog_list_id, static_cast(old_list.pinned_dialogs_.size() + 2), Auto()); } - for (auto &promise : load_list_promises) { - promise.set_value(Unit()); // try again + if (!load_list_promises.empty()) { + LOG(INFO) << "Retry loading of chats in " << dialog_list_id; + for (auto &promise : load_list_promises) { + promise.set_value(Unit()); // try again + } } return; } @@ -19919,6 +19888,7 @@ void MessagesManager::on_animated_emoji_message_clicked(FullMessageId full_messa } void MessagesManager::open_dialog(Dialog *d) { + CHECK(!td_->auth_manager_->is_bot()); DialogId dialog_id = d->dialog_id; if (!have_input_peer(dialog_id, AccessRights::Read)) { return; @@ -21889,9 +21859,8 @@ void MessagesManager::on_search_dialog_messages_db_result(int64 random_id, Dialo MessageSearchFilter filter, int32 offset, int32 limit, Result> r_messages, Promise<> promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + if (r_messages.is_error()) { LOG(ERROR) << "Failed to get messages from the database: " << r_messages.error(); if (first_db_message_id != MessageId::min() && dialog_id.get_type() != DialogType::SecretChat && @@ -22036,7 +22005,7 @@ MessagesManager::FoundMessages MessagesManager::offline_search_messages(DialogId void MessagesManager::on_messages_db_fts_result(Result result, string offset, int32 limit, int64 random_id, Promise &&promise) { if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); + result = Global::request_aborted_error(); } if (result.is_error()) { found_fts_messages_.erase(random_id); @@ -22069,7 +22038,7 @@ void MessagesManager::on_messages_db_calls_result(Result Promise<> &&promise) { CHECK(!first_db_message_id.is_scheduled()); if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); + result = Global::request_aborted_error(); } if (result.is_error()) { found_call_messages_.erase(random_id); @@ -22228,9 +22197,8 @@ MessageId MessagesManager::find_message_by_date(const Message *m, int32 date) { void MessagesManager::on_get_dialog_message_by_date_from_database(DialogId dialog_id, int32 date, int64 random_id, Result result, Promise promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); + Dialog *d = get_dialog(dialog_id); CHECK(d != nullptr); if (result.is_ok()) { @@ -22276,7 +22244,10 @@ void MessagesManager::get_dialog_message_by_date_from_server(const Dialog *d, in } void MessagesManager::on_get_dialog_message_by_date_success(DialogId dialog_id, int32 date, int64 random_id, - vector> &&messages) { + vector> &&messages, + Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + auto it = get_dialog_message_by_date_results_.find(random_id); CHECK(it != get_dialog_message_by_date_results_.end()); auto &result = it->second; @@ -22302,10 +22273,12 @@ void MessagesManager::on_get_dialog_message_by_date_success(DialogId dialog_id, } get_dialog_message_by_date_results_[random_id] = {dialog_id, message_id}; // TODO result must be adjusted by local messages + promise.set_value(Unit()); return; } } } + promise.set_value(Unit()); } void MessagesManager::on_get_dialog_message_by_date_fail(int64 random_id) { @@ -22459,10 +22432,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId CHECK(-limit < offset && offset <= 0); CHECK(offset < 0 || from_the_end); CHECK(!from_message_id.is_scheduled()); - - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); if (!have_input_peer(dialog_id, AccessRights::Read)) { LOG(WARNING) << "Ignore result of get_history_from_database in " << dialog_id; @@ -22698,15 +22668,13 @@ void MessagesManager::get_history_from_the_end(DialogId dialog_id, bool from_dat void MessagesManager::get_history_from_the_end_impl(const Dialog *d, bool from_database, bool only_local, Promise &&promise) { CHECK(d != nullptr); + TRY_STATUS_PROMISE(promise, G()->close_status()); auto dialog_id = d->dialog_id; if (!have_input_peer(dialog_id, AccessRights::Read)) { // can't get history in dialogs without read access return promise.set_value(Unit()); } - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } if (!d->first_database_message_id.is_valid() && !d->have_full_history) { from_database = false; } @@ -22756,15 +22724,13 @@ void MessagesManager::get_history_impl(const Dialog *d, MessageId from_message_i bool from_database, bool only_local, Promise &&promise) { CHECK(d != nullptr); CHECK(from_message_id.is_valid()); + TRY_STATUS_PROMISE(promise, G()->close_status()); auto dialog_id = d->dialog_id; if (!have_input_peer(dialog_id, AccessRights::Read)) { // can't get history in dialogs without read access return promise.set_value(Unit()); } - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } if ((!d->first_database_message_id.is_valid() || from_message_id <= d->first_database_message_id) && !d->have_full_history) { from_database = false; @@ -22844,7 +22810,7 @@ vector MessagesManager::get_dialog_scheduled_messages(DialogId dialog Promise &&promise) { LOG(INFO) << "Get scheduled messages in " << dialog_id; if (G()->close_flag()) { - promise.set_error(Status::Error(500, "Request aborted")); + promise.set_error(Global::request_aborted_error()); return {}; } @@ -22947,7 +22913,7 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id load_scheduled_messages_from_database_queries_.erase(it); for (auto &promise : promises) { - promise.set_error(Status::Error(500, "Request aborted")); + promise.set_error(Global::request_aborted_error()); } return; } @@ -27121,10 +27087,7 @@ void MessagesManager::upload_imported_messages(DialogId dialog_id, FileId file_i void MessagesManager::start_import_messages(DialogId dialog_id, int64 import_id, vector &&attached_file_ids, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - + TRY_STATUS_PROMISE(promise, G()->close_status()); TRY_STATUS_PROMISE(promise, can_send_message(dialog_id)); auto pending_message_import = make_unique(); @@ -27140,8 +27103,8 @@ void MessagesManager::start_import_messages(DialogId dialog_id, int64 import_id, } while (random_id == 0 || pending_message_imports_.find(random_id) != pending_message_imports_.end()); pending_message_imports_[random_id] = std::move(pending_message_import); - multipromise.add_promise(PromiseCreator::lambda([random_id](Result result) { - send_closure_later(G()->messages_manager(), &MessagesManager::on_imported_message_attachments_uploaded, random_id, + multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), random_id](Result result) { + send_closure_later(actor_id, &MessagesManager::on_imported_message_attachments_uploaded, random_id, std::move(result)); })); auto lock_promise = multipromise.get_promise(); @@ -27171,7 +27134,7 @@ void MessagesManager::upload_imported_message_attachment(DialogId dialog_id, int void MessagesManager::on_imported_message_attachments_uploaded(int64 random_id, Result &&result) { if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); + result = Global::request_aborted_error(); } auto it = pending_message_imports_.find(random_id); @@ -27489,7 +27452,7 @@ MessagesManager::MessageNotificationGroup MessagesManager::get_message_notificat CHECK(d != nullptr); } else if (G()->parameters().use_message_db) { auto *dialog_db = G()->td_db()->get_dialog_db_sync(); - dialog_db->begin_transaction().ensure(); // read transaction + dialog_db->begin_read_transaction().ensure(); auto r_value = dialog_db->get_notification_group(group_id); if (r_value.is_ok()) { VLOG(notifications) << "Loaded " << r_value.ok() << " from database by " << group_id; @@ -27784,7 +27747,7 @@ vector MessagesManager::get_message_notification_group_key << from_group_key; auto *dialog_db = G()->td_db()->get_dialog_db_sync(); - dialog_db->begin_transaction().ensure(); // read transaction + dialog_db->begin_read_transaction().ensure(); Result> r_notification_group_keys = dialog_db->get_notification_groups_by_last_notification_date(from_group_key, limit); r_notification_group_keys.ensure(); @@ -27902,7 +27865,7 @@ void MessagesManager::on_get_message_notifications_from_database(DialogId dialog Result> result, Promise> promise) { if (G()->close_flag()) { - result = Status::Error(500, "Request aborted"); + result = Global::request_aborted_error(); } if (result.is_error()) { return promise.set_error(result.move_as_error()); @@ -28444,6 +28407,8 @@ bool MessagesManager::add_new_message_notification(Dialog *d, Message *m, bool f void MessagesManager::flush_pending_new_message_notifications(DialogId dialog_id, bool from_mentions, DialogId settings_dialog_id) { + // flush pending notifications even while closing + auto d = get_dialog(dialog_id); CHECK(d != nullptr); auto &pending_notifications = @@ -28463,10 +28428,8 @@ void MessagesManager::flush_pending_new_message_notifications(DialogId dialog_id auto it = pending_notifications.begin(); while (it != pending_notifications.end() && it->first == DialogId()) { auto m = get_message(d, it->second); - if (m != nullptr) { - if (add_new_message_notification(d, m, true)) { - on_message_changed(d, m, false, "flush_pending_new_message_notifications"); - } + if (m != nullptr && add_new_message_notification(d, m, true)) { + on_message_changed(d, m, false, "flush_pending_new_message_notifications"); } ++it; } @@ -30199,7 +30162,7 @@ void MessagesManager::on_update_dialog_group_call(DialogId dialog_id, bool has_a d->is_group_call_empty = is_group_call_empty; on_dialog_updated(dialog_id, "on_update_dialog_group_call"); - if (has_active_group_call && !d->active_group_call_id.is_valid()) { + if (has_active_group_call && !d->active_group_call_id.is_valid() && !td_->auth_manager_->is_bot()) { repair_dialog_active_group_call_id(dialog_id); } } @@ -30668,6 +30631,8 @@ uint64 MessagesManager::save_get_dialog_from_server_log_event(DialogId dialog_id void MessagesManager::send_get_dialog_query(DialogId dialog_id, Promise &&promise, uint64 log_event_id, const char *source) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + if (td_->auth_manager_->is_bot() || dialog_id.get_type() == DialogType::SecretChat) { if (log_event_id != 0) { binlog_erase(G()->td_db()->get_binlog(), log_event_id); @@ -30709,6 +30674,10 @@ void MessagesManager::send_get_dialog_query(DialogId dialog_id, Promise && } void MessagesManager::on_get_dialog_query_finished(DialogId dialog_id, Status &&status) { + if (G()->close_flag()) { + return; + } + LOG(INFO) << "Finished getting " << dialog_id << " with result " << status; auto it = get_dialog_queries_.find(dialog_id); CHECK(it != get_dialog_queries_.end()); @@ -33669,12 +33638,20 @@ void MessagesManager::do_delete_message_log_event(const DeleteMessageLogEvent &l } MultiPromiseActorSafe mpas{"DeleteMessageMultiPromiseActor"}; - mpas.add_promise(PromiseCreator::lambda([log_event_id](Result result) { - if (result.is_error() || G()->close_flag()) { - return; - } - binlog_erase(G()->td_db()->get_binlog(), log_event_id); - })); + mpas.add_promise( + PromiseCreator::lambda([log_event_id, context_weak_ptr = get_context_weak_ptr()](Result result) { + auto context = context_weak_ptr.lock(); + if (result.is_error() || context == nullptr) { + return; + } + CHECK(context->get_id() == Global::ID); + auto global = static_cast(context.get()); + if (global->close_flag()) { + return; + } + + binlog_erase(global->td_db()->get_binlog(), log_event_id); + })); auto lock = mpas.get_promise(); for (auto file_id : log_event.file_ids_) { @@ -34599,7 +34576,7 @@ void MessagesManager::fix_new_dialog(Dialog *d, unique_ptr &&last_datab // asynchronously get action bar from the server reget_dialog_action_bar(dialog_id, "fix_new_dialog"); } - if (d->has_active_group_call && !d->active_group_call_id.is_valid()) { + if (d->has_active_group_call && !d->active_group_call_id.is_valid() && !td_->auth_manager_->is_bot()) { repair_dialog_active_group_call_id(dialog_id); } @@ -35357,7 +35334,7 @@ void MessagesManager::update_last_dialog_date(FolderId folder_id) { << folder->last_server_dialog_date_.get_dialog_id().get(); G()->td_db()->get_binlog_pmc()->set(PSTRING() << "last_server_dialog_date" << folder_id.get(), last_server_dialog_date_string); - LOG(INFO) << "Save last server dialog date " << last_server_dialog_date_string; + LOG(INFO) << "Save last server dialog date " << folder->last_server_dialog_date_; folder->last_database_server_dialog_date_ = folder->last_server_dialog_date_; folder->last_loaded_database_dialog_date_ = folder->last_server_dialog_date_; } @@ -35432,6 +35409,7 @@ void MessagesManager::update_list_last_dialog_date(DialogList &list) { auto old_dialog_total_count = get_dialog_total_count(list); auto old_last_dialog_date = list.list_last_dialog_date_; if (!do_update_list_last_dialog_date(list, get_dialog_list_folder_ids(list))) { + LOG(INFO) << "Don't need to update last dialog date in " << list.dialog_list_id; return; } @@ -35464,9 +35442,12 @@ void MessagesManager::update_list_last_dialog_date(DialogList &list) { } if (list.list_last_dialog_date_ == MAX_DIALOG_DATE) { - recalc_unread_count(list.dialog_list_id, old_dialog_total_count); + recalc_unread_count(list.dialog_list_id, old_dialog_total_count, true); } + LOG(INFO) << "After updating last dialog date in " << list.dialog_list_id << " to " << list.list_last_dialog_date_ + << " have is_list_further_loaded == " << is_list_further_loaded << " and " << list.load_list_queries_.size() + << " pending load list queries"; if (is_list_further_loaded && !list.load_list_queries_.empty()) { auto promises = std::move(list.load_list_queries_); list.load_list_queries_.clear(); @@ -36764,7 +36745,7 @@ void MessagesManager::speculatively_update_active_group_call_id(Dialog *d, const } } else { d->expected_active_group_call_id = input_group_call_id; - if (d->active_group_call_id != input_group_call_id) { + if (d->active_group_call_id != input_group_call_id && !td_->auth_manager_->is_bot()) { repair_dialog_active_group_call_id(d->dialog_id); } } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 98b3c3646..db8805173 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -189,7 +189,7 @@ class MessagesManager final : public Actor { int32 total_count = 0; bool is_channel_messages = false; }; - MessagesInfo on_get_messages(tl_object_ptr &&messages_ptr, const char *source); + MessagesInfo get_messages_info(tl_object_ptr &&messages_ptr, const char *source); void get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info, Promise &&promise); @@ -197,7 +197,7 @@ class MessagesManager final : public Actor { void get_channel_differences_if_needed(MessagesInfo &&messages_info, Promise &&promise); void on_get_messages(vector> &&messages, bool is_channel_message, - bool is_scheduled, const char *source); + bool is_scheduled, Promise &&promise, const char *source); void on_get_history(DialogId dialog_id, MessageId from_message_id, MessageId old_last_new_message_id, int32 offset, int32 limit, bool from_the_end, vector> &&messages, @@ -211,7 +211,8 @@ class MessagesManager final : public Actor { MessageId from_message_id, int32 offset, int32 limit, MessageSearchFilter filter, MessageId top_thread_message_id, int64 random_id, int32 total_count, - vector> &&messages); + vector> &&messages, + Promise &&promise); void on_failed_dialog_messages_search(DialogId dialog_id, int64 random_id); void on_get_dialog_message_count(DialogId dialog_id, MessageSearchFilter filter, int32 total_count, @@ -220,7 +221,7 @@ class MessagesManager final : public Actor { void on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id, MessageId offset_message_id, int32 limit, MessageSearchFilter filter, int32 min_date, int32 max_date, int64 random_id, int32 total_count, - vector> &&messages); + vector> &&messages, Promise &&promise); void on_failed_messages_search(int64 random_id); void on_get_scheduled_server_messages(DialogId dialog_id, uint32 generation, @@ -547,13 +548,11 @@ class MessagesManager final : public Actor { void block_message_sender_from_replies(MessageId message_id, bool delete_message, bool delete_all_messages, bool report_spam, Promise &&promise); - std::pair> get_blocked_dialogs(int32 offset, int32 limit, int64 &random_id, - Promise &&promise); + void get_blocked_dialogs(int32 offset, int32 limit, Promise> &&promise); - void on_get_blocked_dialogs(int32 offset, int32 limit, int64 random_id, int32 total_count, - vector> &&blocked_peers); - - void on_failed_get_blocked_dialogs(int64 random_id); + void on_get_blocked_dialogs(int32 offset, int32 limit, int32 total_count, + vector> &&blocked_peers, + Promise> &&promise); bool can_get_message_statistics(FullMessageId full_message_id); @@ -728,7 +727,8 @@ class MessagesManager final : public Actor { int64 get_dialog_message_by_date(DialogId dialog_id, int32 date, Promise &&promise); void on_get_dialog_message_by_date_success(DialogId dialog_id, int32 date, int64 random_id, - vector> &&messages); + vector> &&messages, + Promise &&promise); void on_get_dialog_message_by_date_fail(int64 random_id); @@ -1743,6 +1743,8 @@ class MessagesManager final : public Actor { void add_secret_message(unique_ptr pending_secret_message, Promise lock_promise = Auto()); + void on_add_secret_message_ready(int64 token); + void finish_add_secret_message(unique_ptr pending_secret_message); void finish_delete_secret_messages(DialogId dialog_id, std::vector random_ids, Promise<> promise); @@ -2133,7 +2135,7 @@ class MessagesManager final : public Actor { void load_folder_dialog_list(FolderId folder_id, int32 limit, bool only_local); - void on_load_folder_dialog_list_fail(FolderId folder_id, Status error); + void on_load_folder_dialog_list(FolderId folder_id, Result &&result); void load_folder_dialog_list_from_database(FolderId folder_id, int32 limit, Promise &&promise); @@ -2376,7 +2378,7 @@ class MessagesManager final : public Actor { void on_get_secret_chat_total_count(DialogListId dialog_list_id, int32 total_count); - void recalc_unread_count(DialogListId dialog_list_id, int32 old_dialog_total_count = -1); + void recalc_unread_count(DialogListId dialog_list_id, int32 old_dialog_total_count, bool force); td_api::object_ptr get_update_chat_filters_object() const; @@ -3273,9 +3275,6 @@ class MessagesManager final : public Actor { }; std::unordered_map found_common_dialogs_; - std::unordered_map>> - found_blocked_dialogs_; // random_id -> [total_count, [dialog_id]...] - std::unordered_map get_dialog_message_by_date_results_; std::unordered_map>> diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index bac4a3831..0e3cf7203 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -839,7 +839,7 @@ void PasswordManager::start_up() { void PasswordManager::hangup() { container_.for_each( - [](auto id, Promise &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); + [](auto id, Promise &promise) { promise.set_error(Global::request_aborted_error()); }); stop(); } diff --git a/td/telegram/PrivacyManager.cpp b/td/telegram/PrivacyManager.cpp index 0e8575eb6..60c426c15 100644 --- a/td/telegram/PrivacyManager.cpp +++ b/td/telegram/PrivacyManager.cpp @@ -561,7 +561,7 @@ void PrivacyManager::send_with_promise(NetQueryPtr query, Promise p void PrivacyManager::hangup() { container_.for_each( - [](auto id, Promise &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); + [](auto id, Promise &promise) { promise.set_error(Global::request_aborted_error()); }); stop(); } diff --git a/td/telegram/RecentDialogList.cpp b/td/telegram/RecentDialogList.cpp index 5b332a009..9006385bb 100644 --- a/td/telegram/RecentDialogList.cpp +++ b/td/telegram/RecentDialogList.cpp @@ -129,6 +129,13 @@ void RecentDialogList::on_load_dialogs(vector &&found_dialogs) { auto promises = std::move(load_list_queries_); CHECK(!promises.empty()); + if (G()->close_flag()) { + for (auto &promise : promises) { + promise.set_error(Global::request_aborted_error()); + } + return; + } + auto newly_found_dialogs = std::move(dialog_ids_); reset_to_empty(dialog_ids_); diff --git a/td/telegram/RequestActor.h b/td/telegram/RequestActor.h index 715d6c5e6..0823e0f6b 100644 --- a/td/telegram/RequestActor.h +++ b/td/telegram/RequestActor.h @@ -7,6 +7,7 @@ #pragma once #include "td/telegram/AuthManager.h" +#include "td/telegram/Global.h" #include "td/telegram/Td.h" #include "td/telegram/td_api.h" @@ -127,7 +128,7 @@ class RequestActor : public Actor { } void hangup() final { - do_send_error(Status::Error(500, "Request aborted")); + do_send_error(Global::request_aborted_error()); stop(); } diff --git a/td/telegram/SecretChatActor.cpp b/td/telegram/SecretChatActor.cpp index b5fad2453..74ea528c8 100644 --- a/td/telegram/SecretChatActor.cpp +++ b/td/telegram/SecretChatActor.cpp @@ -1304,16 +1304,6 @@ Status SecretChatActor::do_inbound_message_decrypted(unique_ptrrandom_id_, std::move(save_message_finish)); break; default: - /* -decryptedMessageActionResend#511110b0 start_seq_no:int end_seq_no:int = DecryptedMessageAction; -decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction; -decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction; -decryptedMessageActionRequestKey#f3c9611b exchange_id:long g_a:bytes = DecryptedMessageAction; -decryptedMessageActionAcceptKey#6fe1735b exchange_id:long g_b:bytes key_fingerprint:long = DecryptedMessageAction; -decryptedMessageActionAbortKey#dd05ec6b exchange_id:long = DecryptedMessageAction; -decryptedMessageActionCommitKey#ec2e0b9b exchange_id:long key_fingerprint:long = DecryptedMessageAction; -decryptedMessageActionNoop#a82fdd63 = DecryptedMessageAction; - */ save_message_finish.set_value(Unit()); break; } @@ -1379,7 +1369,7 @@ void SecretChatActor::on_save_changes_start(ChangesProcessor::Id sa } void SecretChatActor::on_inbound_save_message_finish(uint64 state_id) { - if (close_flag_) { + if (close_flag_ || context_->close_flag()) { return; } auto *state = inbound_message_states_.get(state_id); diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp index ccecc5784..47cbb5d89 100644 --- a/td/telegram/SecureManager.cpp +++ b/td/telegram/SecureManager.cpp @@ -582,7 +582,7 @@ void SetSecureValue::loop() { } void SetSecureValue::hangup() { - on_error(Status::Error(406, "Request aborted")); + on_error(Status::Error(406, "Request canceled")); } void SetSecureValue::tear_down() { @@ -1294,7 +1294,7 @@ void SecureManager::get_preferred_country_language(string country_code, void SecureManager::hangup() { container_.for_each( - [](auto id, Promise &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); + [](auto id, Promise &promise) { promise.set_error(Global::request_aborted_error()); }); dec_refcnt(); } diff --git a/td/telegram/SequenceDispatcher.cpp b/td/telegram/SequenceDispatcher.cpp index a8614fbb2..92eb9c5d5 100644 --- a/td/telegram/SequenceDispatcher.cpp +++ b/td/telegram/SequenceDispatcher.cpp @@ -226,7 +226,7 @@ void SequenceDispatcher::tear_down() { continue; } data.state_ = State::Dummy; - data.query_->set_error(Status::Error(500, "Request aborted")); + data.query_->set_error(Global::request_aborted_error()); do_finish(data); } } diff --git a/td/telegram/SponsoredMessageManager.cpp b/td/telegram/SponsoredMessageManager.cpp index dde5baf98..d4d4407bf 100644 --- a/td/telegram/SponsoredMessageManager.cpp +++ b/td/telegram/SponsoredMessageManager.cpp @@ -148,8 +148,25 @@ void SponsoredMessageManager::delete_cached_sponsored_messages(DialogId dialog_i td_api::object_ptr SponsoredMessageManager::get_sponsored_message_object( DialogId dialog_id, const SponsoredMessage &sponsored_message) const { + td_api::object_ptr link; + switch (sponsored_message.sponsor_dialog_id.get_type()) { + case DialogType::User: { + auto user_id = sponsored_message.sponsor_dialog_id.get_user_id(); + if (!td_->contacts_manager_->is_user_bot(user_id)) { + break; + } + auto bot_username = td_->contacts_manager_->get_user_username(user_id); + if (bot_username.empty()) { + break; + } + link = td_api::make_object(bot_username, sponsored_message.start_param); + break; + } + default: + break; + } return td_api::make_object( - sponsored_message.local_id, sponsored_message.sponsor_dialog_id.get(), sponsored_message.start_param, + sponsored_message.local_id, sponsored_message.sponsor_dialog_id.get(), std::move(link), get_message_content_object(sponsored_message.content.get(), td_, dialog_id, 0, false, true, -1)); } @@ -201,7 +218,7 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages( CHECK(messages->message_random_ids.empty()); if (result.is_ok() && G()->close_flag()) { - result = Status::Error(500, "Request aborted"); + result = Global::request_aborted_error(); } if (result.is_error()) { dialog_sponsored_messages_.erase(dialog_id); diff --git a/td/telegram/StickersManager.cpp b/td/telegram/StickersManager.cpp index a525bf744..7c8a3f8c0 100644 --- a/td/telegram/StickersManager.cpp +++ b/td/telegram/StickersManager.cpp @@ -2293,11 +2293,12 @@ StickerSetId StickersManager::on_get_input_sticker_set(FileId sticker_file_id, } auto set_id = search_sticker_set(set->short_name_, load_data_multipromise_ptr->get_promise()); if (!set_id.is_valid()) { - load_data_multipromise_ptr->add_promise( - PromiseCreator::lambda([td = td_, sticker_file_id, short_name = set->short_name_](Result result) { + load_data_multipromise_ptr->add_promise(PromiseCreator::lambda( + [actor_id = actor_id(this), sticker_file_id, short_name = set->short_name_](Result result) { if (result.is_ok()) { // just in case - td->stickers_manager_->on_resolve_sticker_set_short_name(sticker_file_id, short_name); + send_closure(actor_id, &StickersManager::on_resolve_sticker_set_short_name, sticker_file_id, + short_name); } })); } @@ -2317,6 +2318,10 @@ StickerSetId StickersManager::on_get_input_sticker_set(FileId sticker_file_id, } void StickersManager::on_resolve_sticker_set_short_name(FileId sticker_file_id, const string &short_name) { + if (G()->close_flag()) { + return; + } + LOG(INFO) << "Resolve sticker " << sticker_file_id << " set to " << short_name; StickerSetId set_id = search_sticker_set(short_name, Auto()); if (set_id.is_valid()) { @@ -3841,9 +3846,7 @@ void StickersManager::reload_sticker_set(StickerSetId sticker_set_id, int64 acce void StickersManager::do_reload_sticker_set(StickerSetId sticker_set_id, tl_object_ptr &&input_sticker_set, Promise &&promise) const { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); td_->create_handler(std::move(promise))->send(sticker_set_id, std::move(input_sticker_set)); } @@ -3911,7 +3914,12 @@ void StickersManager::on_update_dice_emojis() { for (auto &emoji : new_dice_emojis) { if (!td::contains(dice_emojis_, emoji)) { auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_dice(emoji)); - CHECK(!special_sticker_set.id_.is_valid()); + if (special_sticker_set.id_.is_valid()) { + // drop information about the sticker set to reload it + special_sticker_set.id_ = StickerSetId(); + special_sticker_set.access_hash_ = 0; + special_sticker_set.short_name_.clear(); + } if (G()->parameters().use_file_db) { LOG(INFO) << "Load new dice sticker set for emoji " << emoji; @@ -4149,9 +4157,7 @@ void StickersManager::choose_animated_emoji_click_sticker(const StickerSet *stic void StickersManager::send_click_animated_emoji_message_response( FileId sticker_id, Promise> &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); promise.set_value(get_sticker_object(sticker_id)); } @@ -5308,9 +5314,8 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri } while (random_id == 0 || pending_new_sticker_sets_.find(random_id) != pending_new_sticker_sets_.end()); pending_new_sticker_sets_[random_id] = std::move(pending_new_sticker_set); - multipromise.add_promise(PromiseCreator::lambda([random_id](Result result) { - send_closure_later(G()->stickers_manager(), &StickersManager::on_new_stickers_uploaded, random_id, - std::move(result)); + multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), random_id](Result result) { + send_closure_later(actor_id, &StickersManager::on_new_stickers_uploaded, random_id, std::move(result)); })); auto lock_promise = multipromise.get_promise(); @@ -5448,6 +5453,9 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result res pending_new_sticker_sets_.erase(it); + if (G()->close_flag()) { + result = Global::request_aborted_error(); + } if (result.is_error()) { pending_new_sticker_set->promise.set_error(result.move_as_error()); return; @@ -5584,9 +5592,7 @@ void StickersManager::set_sticker_set_thumbnail(UserId user_id, string &short_na void StickersManager::do_set_sticker_set_thumbnail(UserId user_id, string short_name, tl_object_ptr &&thumbnail, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); auto it = short_name_to_sticker_set_id_.find(short_name); const StickerSet *sticker_set = it == short_name_to_sticker_set_id_.end() ? nullptr : get_sticker_set(it->second); @@ -6009,9 +6015,7 @@ void StickersManager::add_recent_sticker(bool is_attached, const tl_object_ptr &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); // TODO invokeAfter and log event auto file_view = td_->file_manager_->get_file_view(sticker_id); @@ -6404,9 +6408,7 @@ void StickersManager::add_favorite_sticker(const tl_object_ptr &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); // TODO invokeAfter and log event auto file_view = td_->file_manager_->get_file_view(sticker_id); @@ -6806,8 +6808,8 @@ void StickersManager::on_get_emoji_keywords( const string &language_code, Result> &&result) { auto it = load_emoji_keywords_queries_.find(language_code); CHECK(it != load_emoji_keywords_queries_.end()); - CHECK(!it->second.empty()); auto promises = std::move(it->second); + CHECK(!promises.empty()); load_emoji_keywords_queries_.erase(it); if (result.is_error()) { @@ -6919,8 +6921,7 @@ void StickersManager::on_get_emoji_keywords_difference( } version = keywords->version_; auto *pmc = G()->td_db()->get_sqlite_sync_pmc(); - pmc->begin_transaction().ensure(); - // set must be the first operation to start a write transaction + pmc->begin_write_transaction().ensure(); pmc->set(get_emoji_language_code_version_database_key(language_code), to_string(version)); pmc->set(get_emoji_language_code_last_difference_time_database_key(language_code), to_string(G()->unix_time())); for (auto &keyword_ptr : keywords->keywords_) { diff --git a/td/telegram/StorageManager.cpp b/td/telegram/StorageManager.cpp index 7c52a9f21..184ed6036 100644 --- a/td/telegram/StorageManager.cpp +++ b/td/telegram/StorageManager.cpp @@ -63,8 +63,7 @@ void StorageManager::on_new_file(int64 size, int64 real_size, int32 cnt) { void StorageManager::get_storage_stats(bool need_all_files, int32 dialog_limit, Promise promise) { if (is_closed_) { - promise.set_error(Status::Error(500, "Request aborted")); - return; + return promise.set_error(Global::request_aborted_error()); } if (pending_storage_stats_.size() != 0) { if (stats_dialog_limit_ == dialog_limit && need_all_files == stats_need_all_files_) { @@ -111,7 +110,7 @@ void StorageManager::update_use_storage_optimizer() { void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_file_statistics, Promise promise) { if (is_closed_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } if (!pending_run_gc_[0].empty() || !pending_run_gc_[1].empty()) { close_gc_worker(); @@ -126,7 +125,7 @@ void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_fil std::move(file_stats)); })); - //NB: get_storage_stats will cancel all gc queries, so promise needs to be added after the call + //NB: get_storage_stats will cancel all garbage collection queries, so promise needs to be added after the call pending_run_gc_[return_deleted_file_statistics].push_back(std::move(promise)); } @@ -158,7 +157,7 @@ void StorageManager::create_stats_worker() { void StorageManager::on_all_files(FileGcParameters gc_parameters, Result r_file_stats) { int32 dialog_limit = gc_parameters.dialog_limit; if (is_closed_ && r_file_stats.is_ok()) { - r_file_stats = Status::Error(500, "Request aborted"); + r_file_stats = Global::request_aborted_error(); } if (r_file_stats.is_error()) { return on_gc_finished(dialog_limit, r_file_stats.move_as_error()); @@ -291,7 +290,7 @@ void StorageManager::close_stats_worker() { auto promises = std::move(pending_storage_stats_); pending_storage_stats_.clear(); for (auto &promise : promises) { - promise.set_error(Status::Error(500, "Request aborted")); + promise.set_error(Global::request_aborted_error()); } stats_generation_++; stats_worker_.reset(); @@ -304,7 +303,7 @@ void StorageManager::close_gc_worker() { pending_run_gc_[0].clear(); pending_run_gc_[1].clear(); for (auto &promise : promises) { - promise.set_error(Status::Error(500, "Request aborted")); + promise.set_error(Global::request_aborted_error()); } gc_worker_.reset(); gc_cancellation_token_source_.cancel(); @@ -332,7 +331,7 @@ void StorageManager::schedule_next_gc() { !G()->parameters().enable_storage_optimizer) { next_gc_at_ = 0; cancel_timeout(); - LOG(INFO) << "No next file gc is scheduled"; + LOG(INFO) << "No next file clean up is scheduled"; return; } auto sys_time = static_cast(Clocks::system()); @@ -348,7 +347,7 @@ void StorageManager::schedule_next_gc() { CHECK(next_gc_at >= sys_time); auto next_gc_in = next_gc_at - sys_time; - LOG(INFO) << "Schedule next file gc in " << next_gc_in; + LOG(INFO) << "Schedule next file clean up in " << next_gc_in; next_gc_at_ = Time::now() + next_gc_in; set_timeout_at(next_gc_at_); } @@ -364,7 +363,7 @@ void StorageManager::timeout_expired() { next_gc_at_ = 0; run_gc({}, false, PromiseCreator::lambda([actor_id = actor_id(this)](Result r_stats) { if (!r_stats.is_error() || r_stats.error().code() != 500) { - // do not save gc timestamp if request was canceled + // do not save garbage collection timestamp if request was canceled send_closure(actor_id, &StorageManager::save_last_gc_timestamp); } send_closure(actor_id, &StorageManager::schedule_next_gc); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 8896cc1fc..3ea788a6b 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -1596,15 +1596,22 @@ class GetWebPagePreviewRequest final : public RequestOnceActor { } }; -class GetWebPageInstantViewRequest final : public RequestActor<> { +class GetWebPageInstantViewRequest final : public RequestActor { string url_; bool force_full_; WebPageId web_page_id_; - void do_run(Promise &&promise) final { - web_page_id_ = - td->web_pages_manager_->get_web_page_instant_view(url_, force_full_, get_tries() < 3, std::move(promise)); + void do_run(Promise &&promise) final { + if (get_tries() < 2) { + promise.set_value(std::move(web_page_id_)); + return; + } + td->web_pages_manager_->get_web_page_instant_view(url_, force_full_, std::move(promise)); + } + + void do_set_result(WebPageId &&result) final { + web_page_id_ = result; } void do_send_result() final { @@ -1614,7 +1621,6 @@ class GetWebPageInstantViewRequest final : public RequestActor<> { public: GetWebPageInstantViewRequest(ActorShared td, uint64 request_id, string url, bool force_full) : RequestActor(std::move(td), request_id), url_(std::move(url)), force_full_(force_full) { - set_tries(3); } }; @@ -1856,31 +1862,6 @@ class GetChatEventLogRequest final : public RequestOnceActor { } }; -class GetBlockedMessageSendersRequest final : public RequestActor<> { - int32 offset_; - int32 limit_; - int64 random_id_; - - std::pair> message_senders_; - - void do_run(Promise &&promise) final { - message_senders_ = td->messages_manager_->get_blocked_dialogs(offset_, limit_, random_id_, std::move(promise)); - } - - void do_send_result() final { - auto senders = - transform(message_senders_.second, [messages_manager = td->messages_manager_.get()](DialogId dialog_id) { - return messages_manager->get_message_sender_object(dialog_id, "GetBlockedMessageSendersRequest"); - }); - send_result(td_api::make_object(message_senders_.first, std::move(senders))); - } - - public: - GetBlockedMessageSendersRequest(ActorShared td, uint64 request_id, int32 offset, int32 limit) - : RequestActor(std::move(td), request_id), offset_(offset), limit_(limit), random_id_(0) { - } -}; - class ImportContactsRequest final : public RequestActor<> { vector contacts_; int64 random_id_; @@ -6633,7 +6614,8 @@ void Td::on_request(uint64 id, const td_api::blockMessageSenderFromReplies &requ void Td::on_request(uint64 id, const td_api::getBlockedMessageSenders &request) { CHECK_IS_USER(); - CREATE_REQUEST(GetBlockedMessageSendersRequest, request.offset_, request.limit_); + CREATE_REQUEST_PROMISE(); + messages_manager_->get_blocked_dialogs(request.offset_, request.limit_, std::move(promise)); } void Td::on_request(uint64 id, td_api::addContact &request) { diff --git a/td/telegram/TdDb.cpp b/td/telegram/TdDb.cpp index e0f8cfd17..027667285 100644 --- a/td/telegram/TdDb.cpp +++ b/td/telegram/TdDb.cpp @@ -277,6 +277,8 @@ void TdDb::do_close(Promise<> on_finished, bool destroy_flag) { } binlog_.reset(); } + + lock.set_value(Unit()); } Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, DbKey key, DbKey old_key, diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp index 0ba36bbe7..477477711 100644 --- a/td/telegram/UpdatesManager.cpp +++ b/td/telegram/UpdatesManager.cpp @@ -1656,7 +1656,9 @@ void UpdatesManager::on_pending_updates(vector &&result) mutable { + send_closure(actor_id, &UpdatesManager::on_pending_updates_processed, std::move(result), std::move(promise)); + }); auto lock = mpas.get_promise(); for (auto &update : updates) { @@ -1775,6 +1777,10 @@ void UpdatesManager::on_pending_updates(vector &&result, Promise &&promise) { + promise.set_result(std::move(result)); +} + void UpdatesManager::add_pending_qts_update(tl_object_ptr &&update, int32 qts, Promise &&promise) { CHECK(update != nullptr); diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h index 7a3ef1312..42bf659e4 100644 --- a/td/telegram/UpdatesManager.h +++ b/td/telegram/UpdatesManager.h @@ -267,6 +267,8 @@ class UpdatesManager final : public Actor { void on_pending_updates(vector> &&updates, int32 seq_begin, int32 seq_end, int32 date, double receive_time, Promise &&promise, const char *source); + void on_pending_updates_processed(Result &&result, Promise &&promise); + void process_updates(vector> &&updates, bool force_apply, Promise &&promise); diff --git a/td/telegram/WebPagesManager.cpp b/td/telegram/WebPagesManager.cpp index 71f0e1526..b2d39e69d 100644 --- a/td/telegram/WebPagesManager.cpp +++ b/td/telegram/WebPagesManager.cpp @@ -94,12 +94,12 @@ class GetWebPagePreviewQuery final : public Td::ResultHandler { }; class GetWebPageQuery final : public Td::ResultHandler { - Promise promise_; + Promise promise_; WebPageId web_page_id_; string url_; public: - explicit GetWebPageQuery(Promise &&promise) : promise_(std::move(promise)) { + explicit GetWebPageQuery(Promise &&promise) : promise_(std::move(promise)) { } void send(WebPageId web_page_id, const string &url, int32 hash) { @@ -123,15 +123,15 @@ class GetWebPageQuery final : public Td::ResultHandler { ? web_page->cached_page_views_ : 0; td->web_pages_manager_->on_get_web_page_instant_view_view_count(web_page_id_, view_count); + return promise_.set_value(std::move(web_page_id_)); } else { LOG(ERROR) << "Receive webPageNotModified for " << url_; + return on_error(id, Status::Error(500, "Receive webPageNotModified")); } - } else { - auto web_page_id = td->web_pages_manager_->on_get_web_page(std::move(ptr), DialogId()); - td->web_pages_manager_->on_get_web_page_by_url(url_, web_page_id, false); } - - promise_.set_value(Unit()); + auto web_page_id = td->web_pages_manager_->on_get_web_page(std::move(ptr), DialogId()); + td->web_pages_manager_->on_get_web_page_by_url(url_, web_page_id, false); + promise_.set_value(std::move(web_page_id)); } void on_error(uint64 id, Status status) final { @@ -832,50 +832,44 @@ tl_object_ptr WebPagesManager::get_web_page_preview_result(int6 return get_web_page_object(web_page_id); } -WebPageId WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, bool force, - Promise &&promise) { +void WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, Promise &&promise) { LOG(INFO) << "Trying to get web page instant view for the url \"" << url << '"'; auto it = url_to_web_page_id_.find(url); if (it != url_to_web_page_id_.end()) { - if (it->second == WebPageId() && !force) { + if (it->second == WebPageId()) { // ignore negative caching - reload_web_page_by_url(url, std::move(promise)); - return WebPageId(); + return reload_web_page_by_url(url, std::move(promise)); } return get_web_page_instant_view(it->second, force_full, std::move(promise)); } load_web_page_by_url(url, std::move(promise)); - return WebPageId(); } -WebPageId WebPagesManager::get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise) { +void WebPagesManager::get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise) { LOG(INFO) << "Trying to get web page instant view for " << web_page_id; const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(web_page_id); if (web_page_instant_view == nullptr) { - promise.set_value(Unit()); - return WebPageId(); + return promise.set_value(WebPageId()); } if (!web_page_instant_view->is_loaded || (force_full && !web_page_instant_view->is_full)) { - load_web_page_instant_view(web_page_id, force_full, std::move(promise)); - return WebPageId(); + return load_web_page_instant_view(web_page_id, force_full, std::move(promise)); } if (force_full) { reload_web_page_instant_view(web_page_id); } - promise.set_value(Unit()); - return web_page_id; + promise.set_value(std::move(web_page_id)); } string WebPagesManager::get_web_page_instant_view_database_key(WebPageId web_page_id) { return PSTRING() << "wpiv" << web_page_id.get(); } -void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise) { +void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise) { auto &load_web_page_instant_view_queries = load_web_page_instant_view_queries_[web_page_id]; auto previous_queries = load_web_page_instant_view_queries.partial.size() + load_web_page_instant_view_queries.full.size(); @@ -892,9 +886,10 @@ void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool for if (G()->parameters().use_message_db && !web_page_instant_view->was_loaded_from_database) { LOG(INFO) << "Trying to load " << web_page_id << " instant view from database"; G()->td_db()->get_sqlite_pmc()->get( - get_web_page_instant_view_database_key(web_page_id), PromiseCreator::lambda([web_page_id](string value) { - send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_instant_view_from_database, - web_page_id, std::move(value)); + get_web_page_instant_view_database_key(web_page_id), + PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](string value) { + send_closure(actor_id, &WebPagesManager::on_load_web_page_instant_view_from_database, web_page_id, + std::move(value)); })); } else { reload_web_page_instant_view(web_page_id); @@ -907,14 +902,12 @@ void WebPagesManager::reload_web_page_instant_view(WebPageId web_page_id) { const WebPage *web_page = get_web_page(web_page_id); CHECK(web_page != nullptr && !web_page->instant_view.is_empty); - auto promise = PromiseCreator::lambda([web_page_id](Result<> result) { - send_closure(G()->web_pages_manager(), &WebPagesManager::update_web_page_instant_view_load_requests, web_page_id, - true, std::move(result)); + auto promise = PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](Result result) { + send_closure(actor_id, &WebPagesManager::update_web_page_instant_view_load_requests, web_page_id, true, + std::move(result)); }); - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); td_->create_handler(std::move(promise)) ->send(web_page_id, web_page->url, web_page->instant_view.is_full ? web_page->instant_view.hash : 0); @@ -927,7 +920,7 @@ void WebPagesManager::on_load_web_page_instant_view_from_database(WebPageId web_ CHECK(G()->parameters().use_message_db); LOG(INFO) << "Successfully loaded " << web_page_id << " instant view of size " << value.size() << " from database"; // G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto()); - // return; + // value.clear(); auto web_page_it = web_pages_.find(web_page_id); if (web_page_it == web_pages_.end() || web_page_it->second->instant_view.is_empty) { @@ -936,7 +929,7 @@ void WebPagesManager::on_load_web_page_instant_view_from_database(WebPageId web_ if (!value.empty()) { G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto()); } - update_web_page_instant_view_load_requests(web_page_id, true, Unit()); + update_web_page_instant_view_load_requests(web_page_id, true, web_page_id); return; } WebPage *web_page = web_page_it->second.get(); @@ -966,41 +959,42 @@ void WebPagesManager::on_load_web_page_instant_view_from_database(WebPageId web_ td_->file_manager_->change_files_source(get_web_page_file_source_id(web_page), old_file_ids, new_file_ids); } - update_web_page_instant_view_load_requests(web_page_id, false, Unit()); + update_web_page_instant_view_load_requests(web_page_id, false, web_page_id); } void WebPagesManager::update_web_page_instant_view_load_requests(WebPageId web_page_id, bool force_update, - Result<> result) { - if (G()->close_flag() && result.is_error()) { - result = Status::Error(500, "Request aborted"); + Result r_web_page_id) { + if (G()->close_flag()) { + r_web_page_id = Global::request_aborted_error(); } LOG(INFO) << "Update load requests for " << web_page_id; auto it = load_web_page_instant_view_queries_.find(web_page_id); if (it == load_web_page_instant_view_queries_.end()) { return; } - vector> promises[2]; + vector> promises[2]; promises[0] = std::move(it->second.partial); promises[1] = std::move(it->second.full); reset_to_empty(it->second.partial); reset_to_empty(it->second.full); load_web_page_instant_view_queries_.erase(it); - if (result.is_error()) { - LOG(INFO) << "Receive error " << result.error() << " for load " << web_page_id; + if (r_web_page_id.is_error()) { + LOG(INFO) << "Receive error " << r_web_page_id.error() << " for load " << web_page_id; combine(promises[0], std::move(promises[1])); for (auto &promise : promises[0]) { - promise.set_error(result.error().clone()); + promise.set_error(r_web_page_id.error().clone()); } return; } - LOG(INFO) << "Successfully loaded web page " << web_page_id; - const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(web_page_id); + auto new_web_page_id = r_web_page_id.move_as_ok(); + LOG(INFO) << "Successfully loaded web page " << web_page_id << " as " << new_web_page_id; + const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(new_web_page_id); if (web_page_instant_view == nullptr) { combine(promises[0], std::move(promises[1])); for (auto &promise : promises[0]) { - promise.set_value(Unit()); + promise.set_value(WebPageId()); } return; } @@ -1010,26 +1004,27 @@ void WebPagesManager::update_web_page_instant_view_load_requests(WebPageId web_p } for (auto &promise : promises[0]) { - promise.set_value(Unit()); + promise.set_value(WebPageId(new_web_page_id)); } reset_to_empty(promises[0]); } if (!promises[0].empty() || !promises[1].empty()) { if (force_update) { // protection from cycles - LOG(ERROR) << "Expected to receive " << web_page_id << " from the server, but didn't receive it"; + LOG(ERROR) << "Expected to receive " << web_page_id << '/' << new_web_page_id + << " from the server, but didn't receive it"; combine(promises[0], std::move(promises[1])); for (auto &promise : promises[0]) { - promise.set_value(Unit()); + promise.set_value(WebPageId()); } return; } - auto &load_queries = load_web_page_instant_view_queries_[web_page_id]; + auto &load_queries = load_web_page_instant_view_queries_[new_web_page_id]; auto old_size = load_queries.partial.size() + load_queries.full.size(); combine(load_queries.partial, std::move(promises[0])); combine(load_queries.full, std::move(promises[1])); if (old_size == 0) { - reload_web_page_instant_view(web_page_id); + reload_web_page_instant_view(new_web_page_id); } } } @@ -1049,48 +1044,42 @@ WebPageId WebPagesManager::get_web_page_by_url(const string &url) const { return WebPageId(); } -WebPageId WebPagesManager::get_web_page_by_url(const string &url, Promise &&promise) { +void WebPagesManager::get_web_page_by_url(const string &url, Promise &&promise) { LOG(INFO) << "Trying to get web page identifier for the url \"" << url << '"'; auto it = url_to_web_page_id_.find(url); if (it != url_to_web_page_id_.end()) { - promise.set_value(Unit()); - return it->second; + return promise.set_value(WebPageId(it->second)); } load_web_page_by_url(url, std::move(promise)); - return WebPageId(); } -void WebPagesManager::load_web_page_by_url(const string &url, Promise &&promise) { +void WebPagesManager::load_web_page_by_url(const string &url, Promise &&promise) { if (!G()->parameters().use_message_db) { - reload_web_page_by_url(url, std::move(promise)); - return; + return reload_web_page_by_url(url, std::move(promise)); } LOG(INFO) << "Load \"" << url << '"'; - G()->td_db()->get_sqlite_pmc()->get(get_web_page_url_database_key(url), - PromiseCreator::lambda([url, promise = std::move(promise)](string value) mutable { - send_closure(G()->web_pages_manager(), - &WebPagesManager::on_load_web_page_id_by_url_from_database, url, - value, std::move(promise)); - })); + G()->td_db()->get_sqlite_pmc()->get( + get_web_page_url_database_key(url), + PromiseCreator::lambda([actor_id = actor_id(this), url, promise = std::move(promise)](string value) mutable { + send_closure(actor_id, &WebPagesManager::on_load_web_page_id_by_url_from_database, std::move(url), + std::move(value), std::move(promise)); + })); } -void WebPagesManager::on_load_web_page_id_by_url_from_database(const string &url, string value, - Promise &&promise) { - if (G()->close_flag()) { - return; - } +void WebPagesManager::on_load_web_page_id_by_url_from_database(string url, string value, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + LOG(INFO) << "Successfully loaded url \"" << url << "\" of size " << value.size() << " from database"; // G()->td_db()->get_sqlite_pmc()->erase(get_web_page_url_database_key(web_page_id), Auto()); - // return; + // value.clear(); auto it = url_to_web_page_id_.find(url); if (it != url_to_web_page_id_.end()) { // URL web page has already been loaded - promise.set_value(Unit()); - return; + return promise.set_value(WebPageId(it->second)); } if (!value.empty()) { auto web_page_id = WebPageId(to_integer(value)); @@ -1098,16 +1087,16 @@ void WebPagesManager::on_load_web_page_id_by_url_from_database(const string &url if (have_web_page(web_page_id)) { // URL web page has already been loaded on_get_web_page_by_url(url, web_page_id, true); - promise.set_value(Unit()); + promise.set_value(WebPageId(web_page_id)); return; } - load_web_page_from_database( - web_page_id, - PromiseCreator::lambda([web_page_id, url, promise = std::move(promise)](Result<> result) mutable { - send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_by_url_from_database, web_page_id, - url, std::move(promise), std::move(result)); - })); + load_web_page_from_database(web_page_id, + PromiseCreator::lambda([actor_id = actor_id(this), web_page_id, url = std::move(url), + promise = std::move(promise)](Result result) mutable { + send_closure(actor_id, &WebPagesManager::on_load_web_page_by_url_from_database, + web_page_id, std::move(url), std::move(promise), std::move(result)); + })); return; } else { LOG(ERROR) << "Receive invalid " << web_page_id; @@ -1117,33 +1106,27 @@ void WebPagesManager::on_load_web_page_id_by_url_from_database(const string &url reload_web_page_by_url(url, std::move(promise)); } -void WebPagesManager::on_load_web_page_by_url_from_database(WebPageId web_page_id, const string &url, - Promise &&promise, Result<> result) { +void WebPagesManager::on_load_web_page_by_url_from_database(WebPageId web_page_id, string url, + Promise &&promise, Result &&result) { if (result.is_error()) { CHECK(G()->close_flag()); - promise.set_error(Status::Error(500, "Request aborted")); - return; + return promise.set_error(Global::request_aborted_error()); } const WebPage *web_page = get_web_page(web_page_id); if (web_page == nullptr) { - reload_web_page_by_url(url, std::move(promise)); - return; + return reload_web_page_by_url(url, std::move(promise)); } if (web_page->url != url) { on_get_web_page_by_url(url, web_page_id, true); } - promise.set_value(Unit()); + promise.set_value(WebPageId(web_page_id)); } -void WebPagesManager::reload_web_page_by_url(const string &url, Promise &&promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } - - LOG(INFO) << "Reload url \"" << url << '"'; +void WebPagesManager::reload_web_page_by_url(const string &url, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); td_->create_handler(std::move(promise))->send(WebPageId(), url, 0); } @@ -1528,9 +1511,8 @@ void WebPagesManager::save_web_page(const WebPage *web_page, WebPageId web_page_ LOG(INFO) << "Save " << web_page_id << " to database"; G()->td_db()->get_sqlite_pmc()->set( get_web_page_database_key(web_page_id), log_event_store(*web_page).as_slice().str(), - PromiseCreator::lambda([web_page_id](Result<> result) { - send_closure(G()->web_pages_manager(), &WebPagesManager::on_save_web_page_to_database, web_page_id, - result.is_ok()); + PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](Result<> result) { + send_closure(actor_id, &WebPagesManager::on_save_web_page_to_database, web_page_id, result.is_ok()); })); } @@ -1594,11 +1576,11 @@ void WebPagesManager::load_web_page_from_database(WebPageId web_page_id, Promise auto &load_web_page_queries = load_web_page_from_database_queries_[web_page_id]; load_web_page_queries.push_back(std::move(promise)); if (load_web_page_queries.size() == 1u) { - G()->td_db()->get_sqlite_pmc()->get( - get_web_page_database_key(web_page_id), PromiseCreator::lambda([web_page_id](string value) { - send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_from_database, web_page_id, - std::move(value)); - })); + G()->td_db()->get_sqlite_pmc()->get(get_web_page_database_key(web_page_id), + PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](string value) { + send_closure(actor_id, &WebPagesManager::on_load_web_page_from_database, + web_page_id, std::move(value)); + })); } } @@ -1620,7 +1602,7 @@ void WebPagesManager::on_load_web_page_from_database(WebPageId web_page_id, stri LOG(INFO) << "Successfully loaded " << web_page_id << " of size " << value.size() << " from database"; // G()->td_db()->get_sqlite_pmc()->erase(get_web_page_database_key(web_page_id), Auto()); - // return; + // value.clear(); if (!have_web_page(web_page_id)) { if (!value.empty()) { diff --git a/td/telegram/WebPagesManager.h b/td/telegram/WebPagesManager.h index 0a48a5ee0..cfb06626a 100644 --- a/td/telegram/WebPagesManager.h +++ b/td/telegram/WebPagesManager.h @@ -67,13 +67,13 @@ class WebPagesManager final : public Actor { tl_object_ptr get_web_page_preview_result(int64 request_id); - WebPageId get_web_page_instant_view(const string &url, bool force_full, bool force, Promise &&promise); + void get_web_page_instant_view(const string &url, bool force_full, Promise &&promise); WebPageId get_web_page_by_url(const string &url) const; - WebPageId get_web_page_by_url(const string &url, Promise &&promise); + void get_web_page_by_url(const string &url, Promise &&promise); - void reload_web_page_by_url(const string &url, Promise &&promise); + void reload_web_page_by_url(const string &url, Promise &&promise); void on_get_web_page_preview_success(int64 request_id, const string &url, tl_object_ptr &&message_media_ptr, @@ -125,7 +125,7 @@ class WebPagesManager final : public Actor { const WebPageInstantView *get_web_page_instant_view(WebPageId web_page_id) const; - WebPageId get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise); + void get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise); tl_object_ptr get_web_page_instant_view_object( WebPageId web_page_id, const WebPageInstantView *web_page_instant_view) const; @@ -153,22 +153,23 @@ class WebPagesManager final : public Actor { static string get_web_page_instant_view_database_key(WebPageId web_page_id); - void load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise); + void load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise &&promise); void on_load_web_page_instant_view_from_database(WebPageId web_page_id, string value); void reload_web_page_instant_view(WebPageId web_page_id); - void update_web_page_instant_view_load_requests(WebPageId web_page_id, bool force_update, Result<> result); + void update_web_page_instant_view_load_requests(WebPageId web_page_id, bool force_update, + Result r_web_page_id); static string get_web_page_url_database_key(const string &url); - void load_web_page_by_url(const string &url, Promise &&promise); + void load_web_page_by_url(const string &url, Promise &&promise); - void on_load_web_page_id_by_url_from_database(const string &url, string value, Promise &&promise); + void on_load_web_page_id_by_url_from_database(string url, string value, Promise &&promise); - void on_load_web_page_by_url_from_database(WebPageId web_page_id, const string &url, Promise &&promise, - Result<> result); + void on_load_web_page_by_url_from_database(WebPageId web_page_id, string url, Promise &&promise, + Result &&result); void tear_down() final; @@ -186,8 +187,8 @@ class WebPagesManager final : public Actor { std::unordered_set loaded_from_database_web_pages_; struct PendingWebPageInstantViewQueries { - vector> partial; - vector> full; + vector> partial; + vector> full; }; std::unordered_map load_web_page_instant_view_queries_; diff --git a/td/telegram/files/FileDb.cpp b/td/telegram/files/FileDb.cpp index 31fc394e4..06a0ec530 100644 --- a/td/telegram/files/FileDb.cpp +++ b/td/telegram/files/FileDb.cpp @@ -23,7 +23,6 @@ #include "td/utils/format.h" #include "td/utils/logging.h" #include "td/utils/misc.h" -#include "td/utils/ScopeGuard.h" #include "td/utils/Slice.h" #include "td/utils/SliceBuilder.h" #include "td/utils/Status.h" @@ -78,10 +77,7 @@ class FileDb final : public FileDbInterface { void clear_file_data(FileDbId id, const string &remote_key, const string &local_key, const string &generate_key) { auto &pmc = file_pmc(); - pmc.begin_transaction().ensure(); - SCOPE_EXIT { - pmc.commit_transaction().ensure(); - }; + pmc.begin_write_transaction().ensure(); if (id > current_pmc_id_) { pmc.set("file_id", to_string(id.get())); @@ -89,27 +85,26 @@ class FileDb final : public FileDbInterface { } pmc.erase(PSTRING() << "file" << id.get()); - LOG(DEBUG) << "ERASE " << format::as_hex_dump<4>(Slice(PSLICE() << "file" << id.get())); + // LOG(DEBUG) << "ERASE " << format::as_hex_dump<4>(Slice(PSLICE() << "file" << id.get())); if (!remote_key.empty()) { pmc.erase(remote_key); - LOG(DEBUG) << "ERASE remote " << format::as_hex_dump<4>(Slice(remote_key)); + // LOG(DEBUG) << "ERASE remote " << format::as_hex_dump<4>(Slice(remote_key)); } if (!local_key.empty()) { pmc.erase(local_key); - LOG(DEBUG) << "ERASE local " << format::as_hex_dump<4>(Slice(local_key)); + // LOG(DEBUG) << "ERASE local " << format::as_hex_dump<4>(Slice(local_key)); } if (!generate_key.empty()) { pmc.erase(generate_key); } + + pmc.commit_transaction().ensure(); } void store_file_data(FileDbId id, const string &file_data, const string &remote_key, const string &local_key, const string &generate_key) { auto &pmc = file_pmc(); - pmc.begin_transaction().ensure(); - SCOPE_EXIT { - pmc.commit_transaction().ensure(); - }; + pmc.begin_write_transaction().ensure(); if (id > current_pmc_id_) { pmc.set("file_id", to_string(id.get())); @@ -127,13 +122,12 @@ class FileDb final : public FileDbInterface { if (!generate_key.empty()) { pmc.set(generate_key, to_string(id.get())); } + + pmc.commit_transaction().ensure(); } void store_file_data_ref(FileDbId id, FileDbId new_id) { auto &pmc = file_pmc(); - pmc.begin_transaction().ensure(); - SCOPE_EXIT { - pmc.commit_transaction().ensure(); - }; + pmc.begin_write_transaction().ensure(); if (id > current_pmc_id_) { pmc.set("file_id", to_string(id.get())); @@ -141,18 +135,18 @@ class FileDb final : public FileDbInterface { } do_store_file_data_ref(id, new_id); + + pmc.commit_transaction().ensure(); } void optimize_refs(const std::vector ids, FileDbId main_id) { LOG(INFO) << "Optimize " << ids.size() << " ids in file database to " << main_id.get(); auto &pmc = file_pmc(); - pmc.begin_transaction().ensure(); - SCOPE_EXIT { - pmc.commit_transaction().ensure(); - }; + pmc.begin_write_transaction().ensure(); for (size_t i = 0; i + 1 < ids.size(); i++) { do_store_file_data_ref(ids[i], main_id); } + pmc.commit_transaction().ensure(); } private: @@ -221,10 +215,10 @@ class FileDb final : public FileDbInterface { if (file_data.generate_ != nullptr && new_generate) { generate_key = as_key(*file_data.generate_); } - LOG(DEBUG) << "SAVE " << id.get() << " -> " << file_data << " " - << tag("remote_key", format::as_hex_dump<4>(Slice(remote_key))) - << tag("local_key", format::as_hex_dump<4>(Slice(local_key))) - << tag("generate_key", format::as_hex_dump<4>(Slice(generate_key))); + // LOG(DEBUG) << "SAVE " << id.get() << " -> " << file_data << " " + // << tag("remote_key", format::as_hex_dump<4>(Slice(remote_key))) + // << tag("local_key", format::as_hex_dump<4>(Slice(local_key))) + // << tag("generate_key", format::as_hex_dump<4>(Slice(generate_key))); send_closure(file_db_actor_, &FileDbActor::store_file_data, id, serialize(file_data), remote_key, local_key, generate_key); } @@ -243,7 +237,7 @@ class FileDb final : public FileDbInterface { static Result load_file_data_impl(ActorId file_db_actor_id, SqliteKeyValue &pmc, const string &key, FileDbId current_pmc_id) { - //LOG(DEBUG) << "Load by key " << format::as_hex_dump<4>(Slice(key)); + // LOG(DEBUG) << "Load by key " << format::as_hex_dump<4>(Slice(key)); TRY_RESULT(id, get_id(pmc, key)); vector ids; @@ -270,8 +264,8 @@ class FileDb final : public FileDbInterface { if (ids.size() > 1) { send_closure(file_db_actor_id, &FileDbActor::optimize_refs, std::move(ids), id); } - //LOG(DEBUG) << "By ID " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str)); - //LOG(INFO) << attempt_count; + // LOG(DEBUG) << "By ID " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str)); + // LOG(INFO) << attempt_count; log_event::WithVersion parser(data_str); parser.set_version(static_cast(Version::Initial)); @@ -287,7 +281,7 @@ class FileDb final : public FileDbInterface { static Result get_id(SqliteKeyValue &pmc, const string &key) TD_WARN_UNUSED_RESULT { auto id_str = pmc.get(key); - //LOG(DEBUG) << "Found ID " << id_str << " by key " << format::as_hex_dump<4>(Slice(key)); + // LOG(DEBUG) << "Found ID " << id_str << " by key " << format::as_hex_dump<4>(Slice(key)); if (id_str.empty()) { return Status::Error("There is no such a key in database"); } diff --git a/td/telegram/files/FileGcWorker.cpp b/td/telegram/files/FileGcWorker.cpp index 8ac715eed..d9486e63c 100644 --- a/td/telegram/files/FileGcWorker.cpp +++ b/td/telegram/files/FileGcWorker.cpp @@ -132,7 +132,7 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector 0 || remove_size > 0)) { if (token_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } if (remove_count > 0) { remove_by_count_cnt++; diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 80c91a828..7821a92b6 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -1746,6 +1746,8 @@ void FileManager::change_files_source(FileSourceId file_source_id, const vector< void FileManager::on_file_reference_repaired(FileId file_id, FileSourceId file_source_id, Result &&result, Promise &&promise) { + TRY_STATUS_PROMISE(promise, G()->close_status()); + auto file_view = get_file_view(file_id); CHECK(!file_view.empty()); if (result.is_ok() && @@ -2030,9 +2032,7 @@ void FileManager::get_content(FileId file_id, Promise promise) { void FileManager::read_file_part(FileId file_id, int32 offset, int32 count, int left_tries, Promise> promise) { - if (G()->close_flag()) { - return promise.set_error(Status::Error(500, "Request aborted")); - } + TRY_STATUS_PROMISE(promise, G()->close_status()); if (!file_id.is_valid()) { return promise.set_error(Status::Error(400, "File identifier is invalid")); @@ -2224,8 +2224,8 @@ void FileManager::run_download(FileNodePtr node, bool force_update_priority) { if (priority == 0) { node->set_download_priority(priority); - LOG(INFO) << "Cancel downloading of file " << node->main_file_id_; if (old_priority != 0) { + LOG(INFO) << "Cancel downloading of file " << node->main_file_id_; do_cancel_download(node); } return; @@ -2640,7 +2640,7 @@ void FileManager::run_generate(FileNodePtr node) { } FileView file_view(node); if (!file_view.can_generate()) { - LOG(INFO) << "Skip run_generate, because file " << node->main_file_id_ << " can't be generated"; + // LOG(INFO) << "Skip run_generate, because file " << node->main_file_id_ << " can't be generated"; return; } if (file_view.has_local_location()) { @@ -2732,8 +2732,6 @@ void FileManager::run_upload(FileNodePtr node, std::vector bad_parts) { if (old_priority != 0) { LOG(INFO) << "Cancel file " << file_id << " uploading"; do_cancel_upload(node); - } else { - LOG(INFO) << "File " << file_id << " upload priority is still 0"; } return; } @@ -3872,7 +3870,7 @@ void FileManager::hangup() { while (!queries_container_.empty()) { auto ids = queries_container_.ids(); for (auto id : ids) { - on_error(id, Status::Error(500, "Request aborted")); + on_error(id, Global::request_aborted_error()); } } is_closed_ = true; diff --git a/td/telegram/files/FileStatsWorker.cpp b/td/telegram/files/FileStatsWorker.cpp index 1977c52cc..a5a39bb31 100644 --- a/td/telegram/files/FileStatsWorker.cpp +++ b/td/telegram/files/FileStatsWorker.cpp @@ -161,7 +161,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_ auto passed = Time::now() - start; LOG_IF(INFO, passed > 0.5) << "Get file stats took: " << format::as_time(passed); if (token_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } promise.set_value(std::move(file_stats)); } else { @@ -182,7 +182,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_ }); if (token_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } std::unordered_map hash_to_pos; @@ -191,7 +191,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_ hash_to_pos[std::hash()(full_info.path)] = pos; pos++; if (token_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } } scan_db(token_, [&](DbFileInfo &db_info) { @@ -203,14 +203,14 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_ full_infos[it->second].owner_dialog_id = db_info.owner_dialog_id; }); if (token_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } FileStats file_stats(need_all_files, split_by_owner_dialog_id); for (auto &full_info : full_infos) { file_stats.add(std::move(full_info)); if (token_) { - return promise.set_error(Status::Error(500, "Request aborted")); + return promise.set_error(Global::request_aborted_error()); } } auto passed = Time::now() - start; diff --git a/td/telegram/net/NetActor.h b/td/telegram/net/NetActor.h index e004ceb9a..f2520fc43 100644 --- a/td/telegram/net/NetActor.h +++ b/td/telegram/net/NetActor.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/Global.h" #include "td/telegram/net/NetQuery.h" #include "td/actor/actor.h" @@ -40,7 +41,7 @@ class NetActor : public NetQueryCallback { class NetActorOnce : public NetActor { void hangup() override { - on_error(0, Status::Error(500, "Request aborted")); + on_error(0, Global::request_aborted_error()); stop(); } diff --git a/td/telegram/net/NetQueryDelayer.cpp b/td/telegram/net/NetQueryDelayer.cpp index 6a5e29317..a73f45dc1 100644 --- a/td/telegram/net/NetQueryDelayer.cpp +++ b/td/telegram/net/NetQueryDelayer.cpp @@ -116,7 +116,7 @@ void NetQueryDelayer::on_slot_event(uint64 id) { void NetQueryDelayer::tear_down() { container_.for_each([](auto id, auto &query_slot) { - query_slot.query_->set_error(Status::Error(500, "Request aborted")); + query_slot.query_->set_error(Global::request_aborted_error()); G()->net_query_dispatcher().dispatch(std::move(query_slot.query_)); }); } diff --git a/td/telegram/net/NetQueryDispatcher.cpp b/td/telegram/net/NetQueryDispatcher.cpp index 02cbbb7d3..17459a9e1 100644 --- a/td/telegram/net/NetQueryDispatcher.cpp +++ b/td/telegram/net/NetQueryDispatcher.cpp @@ -6,6 +6,8 @@ // #include "td/telegram/net/NetQueryDispatcher.h" +#include "td/telegram/ConfigShared.h" +#include "td/telegram/Global.h" #include "td/telegram/net/AuthDataShared.h" #include "td/telegram/net/DcAuthManager.h" #include "td/telegram/net/NetQuery.h" @@ -13,9 +15,6 @@ #include "td/telegram/net/PublicRsaKeyShared.h" #include "td/telegram/net/PublicRsaKeyWatchdog.h" #include "td/telegram/net/SessionMultiProxy.h" - -#include "td/telegram/ConfigShared.h" -#include "td/telegram/Global.h" #include "td/telegram/Td.h" #include "td/telegram/TdDb.h" #include "td/telegram/telegram_api.h" @@ -44,7 +43,7 @@ void NetQueryDispatcher::complete_net_query(NetQueryPtr net_query) { void NetQueryDispatcher::dispatch(NetQueryPtr net_query) { // net_query->debug("dispatch"); if (stop_flag_.load(std::memory_order_relaxed)) { - net_query->set_error(Status::Error(500, "Request aborted")); + net_query->set_error(Global::request_aborted_error()); return complete_net_query(std::move(net_query)); } if (G()->shared_config().get_option_boolean("test_flood_wait")) { diff --git a/tdactor/td/actor/impl/Actor-decl.h b/tdactor/td/actor/impl/Actor-decl.h index 8a107375f..f8ae5f5ef 100644 --- a/tdactor/td/actor/impl/Actor-decl.h +++ b/tdactor/td/actor/impl/Actor-decl.h @@ -75,6 +75,7 @@ class Actor : public ObserverBase { void do_migrate(int32 sched_id); uint64 get_link_token(); + std::weak_ptr get_context_weak_ptr() const; std::shared_ptr set_context(std::shared_ptr context); string set_tag(string tag); diff --git a/tdactor/td/actor/impl/Actor.h b/tdactor/td/actor/impl/Actor.h index 3577093ce..b57eeb129 100644 --- a/tdactor/td/actor/impl/Actor.h +++ b/tdactor/td/actor/impl/Actor.h @@ -79,18 +79,26 @@ std::enable_if_t::value> start_migrate(ActorTy Scheduler::instance()->start_migrate_actor(&obj, sched_id); } } + template std::enable_if_t::value> finish_migrate(ActorType &obj) { if (!obj.empty()) { Scheduler::instance()->finish_migrate_actor(&obj); } } + inline uint64 Actor::get_link_token() { return Scheduler::instance()->get_link_token(this); } + +inline std::weak_ptr Actor::get_context_weak_ptr() const { + return info_->get_context_weak_ptr(); +} + inline std::shared_ptr Actor::set_context(std::shared_ptr context) { return info_->set_context(std::move(context)); } + inline string Actor::set_tag(string tag) { auto *ctx = info_->get_context(); string old_tag; @@ -105,12 +113,14 @@ inline string Actor::set_tag(string tag) { inline void Actor::init(ObjectPool::OwnerPtr &&info) { info_ = std::move(info); } + inline ActorInfo *Actor::get_info() { return &*info_; } inline const ActorInfo *Actor::get_info() const { return &*info_; } + inline ObjectPool::OwnerPtr Actor::clear() { return std::move(info_); } diff --git a/tdactor/td/actor/impl/ActorInfo-decl.h b/tdactor/td/actor/impl/ActorInfo-decl.h index ee8a78267..cb9a8e7bd 100644 --- a/tdactor/td/actor/impl/ActorInfo-decl.h +++ b/tdactor/td/actor/impl/ActorInfo-decl.h @@ -86,6 +86,7 @@ class ActorInfo final const Actor *get_actor_unsafe() const; std::shared_ptr set_context(std::shared_ptr context); + std::weak_ptr get_context_weak_ptr() const; ActorContext *get_context(); const ActorContext *get_context() const; CSlice get_name() const; diff --git a/tdactor/td/actor/impl/ActorInfo.h b/tdactor/td/actor/impl/ActorInfo.h index f4a6c088b..226490af9 100644 --- a/tdactor/td/actor/impl/ActorInfo.h +++ b/tdactor/td/actor/impl/ActorInfo.h @@ -156,6 +156,11 @@ inline std::shared_ptr ActorInfo::set_context(std::shared_ptr ActorInfo::get_context_weak_ptr() const { + return context_; +} + inline const ActorContext *ActorInfo::get_context() const { return context_.get(); } diff --git a/tdactor/test/actors_bugs.cpp b/tdactor/test/actors_bugs.cpp index 18ef08f59..0e4843986 100644 --- a/tdactor/test/actors_bugs.cpp +++ b/tdactor/test/actors_bugs.cpp @@ -13,31 +13,29 @@ #include "td/utils/Random.h" #include "td/utils/tests.h" -using namespace td; - TEST(MultiTimeout, bug) { - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 0; sched.init(threads_n); sched.start(); - unique_ptr multi_timeout; + td::unique_ptr multi_timeout; struct Data { - MultiTimeout *multi_timeout; + td::MultiTimeout *multi_timeout; }; Data data; { auto guard = sched.get_main_guard(); - multi_timeout = make_unique("MultiTimeout"); + multi_timeout = td::make_unique("MultiTimeout"); data.multi_timeout = multi_timeout.get(); - multi_timeout->set_callback([](void *void_data, int64 key) { + multi_timeout->set_callback([](void *void_data, td::int64 key) { auto &data = *static_cast(void_data); if (key == 1) { data.multi_timeout->cancel_timeout(key + 1); data.multi_timeout->set_timeout_in(key + 2, 1); } else { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } }); multi_timeout->set_callback_data(&data); @@ -51,9 +49,9 @@ TEST(MultiTimeout, bug) { sched.finish(); } -class TimeoutManager final : public Actor { +class TimeoutManager final : public td::Actor { public: - static int32 count; + static td::int32 count; TimeoutManager() { count++; @@ -70,7 +68,7 @@ class TimeoutManager final : public Actor { LOG(INFO) << "Destroy TimeoutManager"; } - static void on_test_timeout_callback(void *timeout_manager_ptr, int64 id) { + static void on_test_timeout_callback(void *timeout_manager_ptr, td::int64 id) { CHECK(count >= 0); if (count == 0) { LOG(ERROR) << "Receive timeout after manager was closed"; @@ -84,21 +82,21 @@ class TimeoutManager final : public Actor { void test_timeout() { CHECK(count > 0); // we must yield scheduler, so run_main breaks immediately, if timeouts are handled immediately - Scheduler::instance()->yield(); + td::Scheduler::instance()->yield(); } - MultiTimeout test_timeout_{"TestTimeout"}; + td::MultiTimeout test_timeout_{"TestTimeout"}; }; -int32 TimeoutManager::count; +td::int32 TimeoutManager::count; TEST(MultiTimeout, Destroy) { SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 0; sched.init(threads_n); - ActorOwn timeout_manager = sched.create_actor_unsafe(0, "TimeoutManager"); + auto timeout_manager = sched.create_actor_unsafe(0, "TimeoutManager"); TimeoutManager *manager = timeout_manager.get().get_actor_unsafe(); sched.start(); int cnt = 100; @@ -107,12 +105,12 @@ TEST(MultiTimeout, Destroy) { cnt--; if (cnt > 0) { for (int i = 0; i < 2; i++) { - manager->test_timeout_.set_timeout_in(Random::fast(0, 1000000000), Random::fast(2, 5) / 1000.0); + manager->test_timeout_.set_timeout_in(td::Random::fast(0, 1000000000), td::Random::fast(2, 5) / 1000.0); } } else if (cnt == 0) { timeout_manager.reset(); } else if (cnt == -10) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } } sched.finish(); diff --git a/tdactor/test/actors_main.cpp b/tdactor/test/actors_main.cpp index 87d4cac22..a16935d35 100644 --- a/tdactor/test/actors_main.cpp +++ b/tdactor/test/actors_main.cpp @@ -19,18 +19,16 @@ #include #include -using namespace td; - namespace { template static typename ContainerT::value_type &rand_elem(ContainerT &cont) { CHECK(0 < cont.size() && cont.size() <= static_cast(std::numeric_limits::max())); - return cont[Random::fast(0, static_cast(cont.size()) - 1)]; + return cont[td::Random::fast(0, static_cast(cont.size()) - 1)]; } -static uint32 fast_pow_mod_uint32(uint32 x, uint32 p) { - uint32 res = 1; +static td::uint32 fast_pow_mod_uint32(td::uint32 x, td::uint32 p) { + td::uint32 res = 1; while (p) { if (p & 1) { res *= x; @@ -41,18 +39,18 @@ static uint32 fast_pow_mod_uint32(uint32 x, uint32 p) { return res; } -static uint32 slow_pow_mod_uint32(uint32 x, uint32 p) { - uint32 res = 1; - for (uint32 i = 0; i < p; i++) { +static td::uint32 slow_pow_mod_uint32(td::uint32 x, td::uint32 p) { + td::uint32 res = 1; + for (td::uint32 i = 0; i < p; i++) { res *= x; } return res; } struct Query { - uint32 query_id{}; - uint32 result{}; - std::vector todo; + td::uint32 query_id{}; + td::uint32 result{}; + td::vector todo; Query() = default; Query(const Query &) = delete; Query &operator=(const Query &) = delete; @@ -72,25 +70,25 @@ struct Query { } }; -static uint32 fast_calc(Query &q) { - uint32 result = q.result; +static td::uint32 fast_calc(Query &q) { + td::uint32 result = q.result; for (auto x : q.todo) { result = fast_pow_mod_uint32(result, x); } return result; } -class Worker final : public Actor { +class Worker final : public td::Actor { public: explicit Worker(int threads_n) : threads_n_(threads_n) { } - void query(PromiseActor &&promise, uint32 x, uint32 p) { - uint32 result = slow_pow_mod_uint32(x, p); + void query(td::PromiseActor &&promise, td::uint32 x, td::uint32 p) { + td::uint32 result = slow_pow_mod_uint32(x, p); promise.set_value(std::move(result)); (void)threads_n_; - // if (threads_n_ > 1 && Random::fast(0, 9) == 0) { - // migrate(Random::fast(2, threads_n)); + // if (threads_n_ > 1 && td::Random::fast(0, 9) == 0) { + // migrate(td::Random::fast(2, threads_n)); //} } @@ -98,7 +96,7 @@ class Worker final : public Actor { int threads_n_; }; -class QueryActor final : public Actor { +class QueryActor final : public td::Actor { public: class Callback { public: @@ -115,39 +113,39 @@ class QueryActor final : public Actor { explicit QueryActor(int threads_n) : threads_n_(threads_n) { } - void set_callback(unique_ptr callback) { + void set_callback(td::unique_ptr callback) { callback_ = std::move(callback); } - void set_workers(std::vector> workers) { + void set_workers(td::vector> workers) { workers_ = std::move(workers); } void query(Query &&query) { - uint32 x = query.result; - uint32 p = query.next_pow(); - if (Random::fast(0, 3) && (p <= 1000 || workers_.empty())) { + td::uint32 x = query.result; + td::uint32 p = query.next_pow(); + if (td::Random::fast(0, 3) && (p <= 1000 || workers_.empty())) { query.result = slow_pow_mod_uint32(x, p); callback_->on_result(std::move(query)); } else { - auto future = Random::fast(0, 3) == 0 - ? send_promise(rand_elem(workers_), &Worker::query, x, p) - : send_promise(rand_elem(workers_), &Worker::query, x, p); + auto future = td::Random::fast(0, 3) == 0 + ? td::send_promise(rand_elem(workers_), &Worker::query, x, p) + : td::send_promise(rand_elem(workers_), &Worker::query, x, p); if (future.is_ready()) { query.result = future.move_as_ok(); callback_->on_result(std::move(query)); } else { - future.set_event(EventCreator::raw(actor_id(), query.query_id)); + future.set_event(td::EventCreator::raw(actor_id(), query.query_id)); auto query_id = query.query_id; pending_.emplace(query_id, std::make_pair(std::move(future), std::move(query))); } } - if (threads_n_ > 1 && Random::fast(0, 9) == 0) { - migrate(Random::fast(2, threads_n_)); + if (threads_n_ > 1 && td::Random::fast(0, 9) == 0) { + migrate(td::Random::fast(2, threads_n_)); } } - void raw_event(const Event::Raw &event) final { - uint32 id = event.u32; + void raw_event(const td::Event::Raw &event) final { + td::uint32 id = event.u32; auto it = pending_.find(id); auto future = std::move(it->second.first); auto query = std::move(it->second.second); @@ -162,7 +160,7 @@ class QueryActor final : public Actor { stop(); } - void on_start_migrate(int32 sched_id) final { + void on_start_migrate(td::int32 sched_id) final { for (auto &it : pending_) { start_migrate(it.second.first, sched_id); } @@ -174,13 +172,13 @@ class QueryActor final : public Actor { } private: - unique_ptr callback_; - std::map, Query>> pending_; - std::vector> workers_; + td::unique_ptr callback_; + std::map, Query>> pending_; + td::vector> workers_; int threads_n_; }; -class MainQueryActor final : public Actor { +class MainQueryActor final : public td::Actor { class QueryActorCallback final : public QueryActor::Callback { public: void on_result(Query &&query) final { @@ -193,13 +191,13 @@ class MainQueryActor final : public Actor { void on_closed() final { send_closure(parent_id_, &MainQueryActor::on_closed); } - QueryActorCallback(ActorId parent_id, ActorId next_solver) + QueryActorCallback(td::ActorId parent_id, td::ActorId next_solver) : parent_id_(parent_id), next_solver_(next_solver) { } private: - ActorId parent_id_; - ActorId next_solver_; + td::ActorId parent_id_; + td::ActorId next_solver_; }; const int ACTORS_CNT = 10; @@ -212,22 +210,22 @@ class MainQueryActor final : public Actor { void start_up() final { actors_.resize(ACTORS_CNT); for (auto &actor : actors_) { - auto actor_ptr = make_unique(threads_n_); - actor = register_actor("QueryActor", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0) + auto actor_ptr = td::make_unique(threads_n_); + actor = register_actor("QueryActor", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0) .release(); } workers_.resize(WORKERS_CNT); for (auto &worker : workers_) { - auto actor_ptr = make_unique(threads_n_); - worker = - register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0).release(); + auto actor_ptr = td::make_unique(threads_n_); + worker = register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0) + .release(); } for (int i = 0; i < ACTORS_CNT; i++) { ref_cnt_++; send_closure(actors_[i], &QueryActor::set_callback, - make_unique(actor_id(this), actors_[(i + 1) % ACTORS_CNT])); + td::make_unique(actor_id(this), actors_[(i + 1) % ACTORS_CNT])); send_closure(actors_[i], &QueryActor::set_workers, workers_); } yield(); @@ -252,14 +250,14 @@ class MainQueryActor final : public Actor { void on_closed() { ref_cnt_--; if (ref_cnt_ == 0) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } } void wakeup() final { int cnt = 100000; while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) { - if (Random::fast_bool()) { + if (td::Random::fast_bool()) { send_closure(rand_elem(actors_), &QueryActor::query, create_query()); } else { send_closure_later(rand_elem(actors_), &QueryActor::query, create_query()); @@ -276,9 +274,9 @@ class MainQueryActor final : public Actor { } private: - std::map expected_; - std::vector> actors_; - std::vector> workers_; + std::map expected_; + td::vector> actors_; + td::vector> workers_; int out_cnt_ = 0; int in_cnt_ = 0; int query_id_ = 1; @@ -286,46 +284,47 @@ class MainQueryActor final : public Actor { int threads_n_; }; -class SimpleActor final : public Actor { +class SimpleActor final : public td::Actor { public: - explicit SimpleActor(int32 threads_n) : threads_n_(threads_n) { + explicit SimpleActor(td::int32 threads_n) : threads_n_(threads_n) { } void start_up() final { - auto actor_ptr = make_unique(threads_n_); + auto actor_ptr = td::make_unique(threads_n_); worker_ = - register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0).release(); + register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0).release(); yield(); } void wakeup() final { if (q_ == 100000) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); stop(); return; } q_++; - p_ = Random::fast_bool() ? 1 : 10000; - auto future = Random::fast(0, 3) == 0 ? send_promise(worker_, &Worker::query, q_, p_) - : send_promise(worker_, &Worker::query, q_, p_); + p_ = td::Random::fast_bool() ? 1 : 10000; + auto future = td::Random::fast(0, 3) == 0 + ? td::send_promise(worker_, &Worker::query, q_, p_) + : td::send_promise(worker_, &Worker::query, q_, p_); if (future.is_ready()) { auto result = future.move_as_ok(); CHECK(result == fast_pow_mod_uint32(q_, p_)); yield(); } else { - future.set_event(EventCreator::raw(actor_id(), nullptr)); + future.set_event(td::EventCreator::raw(actor_id(), nullptr)); future_ = std::move(future); } - // if (threads_n_ > 1 && Random::fast(0, 2) == 0) { - // migrate(Random::fast(1, threads_n)); + // if (threads_n_ > 1 && td::Random::fast(0, 2) == 0) { + // migrate(td::Random::fast(1, threads_n)); //} } - void raw_event(const Event::Raw &event) final { + void raw_event(const td::Event::Raw &event) final { auto result = future_.move_as_ok(); CHECK(result == fast_pow_mod_uint32(q_, p_)); yield(); } - void on_start_migrate(int32 sched_id) final { + void on_start_migrate(td::int32 sched_id) final { start_migrate(future_, sched_id); } void on_finish_migrate() final { @@ -333,25 +332,26 @@ class SimpleActor final : public Actor { } private: - int32 threads_n_; - ActorId worker_; - FutureActor future_; - uint32 q_ = 1; - uint32 p_ = 0; + td::int32 threads_n_; + td::ActorId worker_; + td::FutureActor future_; + td::uint32 q_ = 1; + td::uint32 p_ = 0; }; } // namespace -class SendToDead final : public Actor { +class SendToDead final : public td::Actor { public: - class Parent final : public Actor { + class Parent final : public td::Actor { public: - explicit Parent(ActorShared<> parent, int ttl = 3) : parent_(std::move(parent)), ttl_(ttl) { + explicit Parent(td::ActorShared<> parent, int ttl = 3) : parent_(std::move(parent)), ttl_(ttl) { } void start_up() final { - set_timeout_in(Random::fast_uint32() % 3 * 0.001); + set_timeout_in(td::Random::fast_uint32() % 3 * 0.001); if (ttl_ != 0) { - child_ = create_actor_on_scheduler( - "Child", Random::fast_uint32() % Scheduler::instance()->sched_count(), actor_shared(this), ttl_ - 1); + child_ = td::create_actor_on_scheduler( + "Child", td::Random::fast_uint32() % td::Scheduler::instance()->sched_count(), actor_shared(this), + ttl_ - 1); } } void timeout_expired() final { @@ -359,29 +359,30 @@ class SendToDead final : public Actor { } private: - ActorOwn child_; - ActorShared<> parent_; + td::ActorOwn child_; + td::ActorShared<> parent_; int ttl_; }; void start_up() final { for (int i = 0; i < 2000; i++) { - create_actor_on_scheduler("Parent", Random::fast_uint32() % Scheduler::instance()->sched_count(), - create_reference(), 4) + td::create_actor_on_scheduler( + "Parent", td::Random::fast_uint32() % td::Scheduler::instance()->sched_count(), create_reference(), 4) .release(); } } - ActorShared<> create_reference() { + td::ActorShared<> create_reference() { ref_cnt_++; return actor_shared(this); } + void hangup_shared() final { ref_cnt_--; if (ref_cnt_ == 0) { ttl_--; if (ttl_ <= 0) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); stop(); } else { start_up(); @@ -389,14 +390,14 @@ class SendToDead final : public Actor { } } - uint32 ttl_{50}; - uint32 ref_cnt_{0}; + td::uint32 ttl_{50}; + td::uint32 ref_cnt_{0}; }; TEST(Actors, send_to_dead) { //TODO: fix CHECK(storage_count_.load() == 0) return; - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 5; sched.init(threads_n); @@ -409,9 +410,7 @@ TEST(Actors, send_to_dead) { } TEST(Actors, main_simple) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 3; sched.init(threads_n); @@ -424,9 +423,7 @@ TEST(Actors, main_simple) { } TEST(Actors, main) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 9; sched.init(threads_n); @@ -438,23 +435,21 @@ TEST(Actors, main) { sched.finish(); } -class DoAfterStop final : public Actor { +class DoAfterStop final : public td::Actor { public: void loop() final { - ptr = make_unique(10); + ptr = td::make_unique(10); stop(); CHECK(*ptr == 10); - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } private: - unique_ptr ptr; + td::unique_ptr ptr; }; TEST(Actors, do_after_stop) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 0; sched.init(threads_n); @@ -466,9 +461,9 @@ TEST(Actors, do_after_stop) { sched.finish(); } -class XContext final : public ActorContext { +class XContext final : public td::ActorContext { public: - int32 get_id() const final { + td::int32 get_id() const final { return 123456789; } @@ -481,12 +476,12 @@ class XContext final : public ActorContext { int x = 1234; }; -class WithXContext final : public Actor { +class WithXContext final : public td::Actor { public: void start_up() final { auto old_context = set_context(std::make_shared()); } - void f(unique_ptr guard) { + void f(td::unique_ptr guard) { } void close() { stop(); @@ -494,25 +489,23 @@ class WithXContext final : public Actor { }; static void check_context() { - auto ptr = static_cast(Scheduler::context()); - CHECK(ptr); + auto ptr = static_cast(td::Scheduler::context()); + CHECK(ptr != nullptr); ptr->validate(); } TEST(Actors, context_during_destruction) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; int threads_n = 0; sched.init(threads_n); { auto guard = sched.get_main_guard(); - auto with_context = create_actor("WithXContext").release(); - send_closure(with_context, &WithXContext::f, create_lambda_guard([] { check_context(); })); + auto with_context = td::create_actor("WithXContext").release(); + send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { check_context(); })); send_closure_later(with_context, &WithXContext::close); - send_closure(with_context, &WithXContext::f, create_lambda_guard([] { check_context(); })); - send_closure(with_context, &WithXContext::f, create_lambda_guard([] { Scheduler::instance()->finish(); })); + send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { check_context(); })); + send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { td::Scheduler::instance()->finish(); })); } sched.start(); while (sched.run_main(10)) { diff --git a/tdactor/test/actors_simple.cpp b/tdactor/test/actors_simple.cpp index 967394a69..0a20369f0 100644 --- a/tdactor/test/actors_simple.cpp +++ b/tdactor/test/actors_simple.cpp @@ -28,40 +28,38 @@ #include namespace { -using namespace td; static const size_t BUF_SIZE = 1024 * 1024; static char buf[BUF_SIZE]; static char buf2[BUF_SIZE]; -static StringBuilder sb(MutableSlice(buf, BUF_SIZE - 1)); -static StringBuilder sb2(MutableSlice(buf2, BUF_SIZE - 1)); +static td::StringBuilder sb(td::MutableSlice(buf, BUF_SIZE - 1)); +static td::StringBuilder sb2(td::MutableSlice(buf2, BUF_SIZE - 1)); -static auto create_queue() { - auto res = std::make_shared>(); +static std::shared_ptr> create_queue() { + auto res = std::make_shared>(); res->init(); return res; } TEST(Actors, SendLater) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); sb.clear(); - Scheduler scheduler; + td::Scheduler scheduler; scheduler.init(0, {create_queue()}, nullptr); auto guard = scheduler.get_guard(); - class Worker final : public Actor { + class Worker final : public td::Actor { public: void f() { sb << "A"; } }; - auto id = create_actor("Worker"); - scheduler.run_no_guard(Timestamp::now()); - send_closure(id, &Worker::f); - send_closure_later(id, &Worker::f); - send_closure(id, &Worker::f); + auto id = td::create_actor("Worker"); + scheduler.run_no_guard(td::Timestamp::in(1)); + td::send_closure(id, &Worker::f); + td::send_closure_later(id, &Worker::f); + td::send_closure(id, &Worker::f); ASSERT_STREQ("A", sb.as_cslice().c_str()); - scheduler.run_no_guard(Timestamp::now()); + scheduler.run_no_guard(td::Timestamp::in(1)); ASSERT_STREQ("AAA", sb.as_cslice().c_str()); } @@ -87,7 +85,7 @@ class X { ~X() = default; }; -class XReceiver final : public Actor { +class XReceiver final : public td::Actor { public: void by_const_ref(const X &) { sb << "[by_const_ref]"; @@ -101,13 +99,12 @@ class XReceiver final : public Actor { }; TEST(Actors, simple_pass_event_arguments) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - Scheduler scheduler; + td::Scheduler scheduler; scheduler.init(0, {create_queue()}, nullptr); auto guard = scheduler.get_guard(); - auto id = create_actor("XR").release(); - scheduler.run_no_guard(Timestamp::now()); + auto id = td::create_actor("XR").release(); + scheduler.run_no_guard(td::Timestamp::in(1)); X x; @@ -122,47 +119,47 @@ TEST(Actors, simple_pass_event_arguments) { // Tmp-->ConstRef sb.clear(); - send_closure(id, &XReceiver::by_const_ref, X()); + td::send_closure(id, &XReceiver::by_const_ref, X()); ASSERT_STREQ("[cnstr_default][by_const_ref]", sb.as_cslice().c_str()); // Tmp-->ConstRef (Delayed) sb.clear(); - send_closure_later(id, &XReceiver::by_const_ref, X()); - scheduler.run_no_guard(Timestamp::now()); + td::send_closure_later(id, &XReceiver::by_const_ref, X()); + scheduler.run_no_guard(td::Timestamp::in(1)); // LOG(ERROR) << sb.as_cslice(); ASSERT_STREQ("[cnstr_default][cnstr_move][by_const_ref]", sb.as_cslice().c_str()); // Tmp-->LvalueRef sb.clear(); - send_closure(id, &XReceiver::by_lvalue_ref, X()); + td::send_closure(id, &XReceiver::by_lvalue_ref, X()); ASSERT_STREQ("[cnstr_default][by_lvalue_ref]", sb.as_cslice().c_str()); // Tmp-->LvalueRef (Delayed) sb.clear(); - send_closure_later(id, &XReceiver::by_lvalue_ref, X()); - scheduler.run_no_guard(Timestamp::now()); + td::send_closure_later(id, &XReceiver::by_lvalue_ref, X()); + scheduler.run_no_guard(td::Timestamp::in(1)); ASSERT_STREQ("[cnstr_default][cnstr_move][by_lvalue_ref]", sb.as_cslice().c_str()); // Tmp-->Value sb.clear(); - send_closure(id, &XReceiver::by_value, X()); + td::send_closure(id, &XReceiver::by_value, X()); ASSERT_STREQ("[cnstr_default][cnstr_move][by_value]", sb.as_cslice().c_str()); // Tmp-->Value (Delayed) sb.clear(); - send_closure_later(id, &XReceiver::by_value, X()); - scheduler.run_no_guard(Timestamp::now()); + td::send_closure_later(id, &XReceiver::by_value, X()); + scheduler.run_no_guard(td::Timestamp::in(1)); ASSERT_STREQ("[cnstr_default][cnstr_move][cnstr_move][by_value]", sb.as_cslice().c_str()); // Var-->ConstRef sb.clear(); - send_closure(id, &XReceiver::by_const_ref, x); + td::send_closure(id, &XReceiver::by_const_ref, x); ASSERT_STREQ("[by_const_ref]", sb.as_cslice().c_str()); // Var-->ConstRef (Delayed) sb.clear(); - send_closure_later(id, &XReceiver::by_const_ref, x); - scheduler.run_no_guard(Timestamp::now()); + td::send_closure_later(id, &XReceiver::by_const_ref, x); + scheduler.run_no_guard(td::Timestamp::in(1)); ASSERT_STREQ("[cnstr_copy][by_const_ref]", sb.as_cslice().c_str()); // Var-->LvalueRef @@ -171,17 +168,17 @@ TEST(Actors, simple_pass_event_arguments) { // Var-->Value sb.clear(); - send_closure(id, &XReceiver::by_value, x); + td::send_closure(id, &XReceiver::by_value, x); ASSERT_STREQ("[cnstr_copy][by_value]", sb.as_cslice().c_str()); // Var-->Value (Delayed) sb.clear(); - send_closure_later(id, &XReceiver::by_value, x); - scheduler.run_no_guard(Timestamp::now()); + td::send_closure_later(id, &XReceiver::by_value, x); + scheduler.run_no_guard(td::Timestamp::in(1)); ASSERT_STREQ("[cnstr_copy][cnstr_move][by_value]", sb.as_cslice().c_str()); } -class PrintChar final : public Actor { +class PrintChar final : public td::Actor { public: PrintChar(char c, int cnt) : char_(c), cnt_(cnt) { } @@ -208,19 +205,18 @@ class PrintChar final : public Actor { // Yield must add actor to the end of queue // TEST(Actors, simple_hand_yield) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - Scheduler scheduler; + td::Scheduler scheduler; scheduler.init(0, {create_queue()}, nullptr); sb.clear(); int cnt = 1000; { auto guard = scheduler.get_guard(); - create_actor("PrintA", 'A', cnt).release(); - create_actor("PrintB", 'B', cnt).release(); - create_actor("PrintC", 'C', cnt).release(); + td::create_actor("PrintA", 'A', cnt).release(); + td::create_actor("PrintB", 'B', cnt).release(); + td::create_actor("PrintC", 'C', cnt).release(); } - scheduler.run(Timestamp::now()); - std::string expected; + scheduler.run(td::Timestamp::in(1)); + td::string expected; for (int i = 0; i < cnt; i++) { expected += "ABC"; } @@ -229,7 +225,7 @@ TEST(Actors, simple_hand_yield) { class Ball { public: - friend void start_migrate(Ball &ball, int32 sched_id) { + friend void start_migrate(Ball &ball, td::int32 sched_id) { sb << "start"; } friend void finish_migrate(Ball &ball) { @@ -237,30 +233,30 @@ class Ball { } }; -class Pong final : public Actor { +class Pong final : public td::Actor { public: void pong(Ball ball) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } }; -class Ping final : public Actor { +class Ping final : public td::Actor { public: - explicit Ping(ActorId pong) : pong_(pong) { + explicit Ping(td::ActorId pong) : pong_(pong) { } void start_up() final { - send_closure(pong_, &Pong::pong, Ball()); + td::send_closure(pong_, &Pong::pong, Ball()); } private: - ActorId pong_; + td::ActorId pong_; }; TEST(Actors, simple_migrate) { sb.clear(); sb2.clear(); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(2); auto pong = scheduler.create_actor_unsafe(2, "Pong").release(); scheduler.create_actor_unsafe(1, "Ping", pong).release(); @@ -277,7 +273,7 @@ TEST(Actors, simple_migrate) { #endif } -class OpenClose final : public Actor { +class OpenClose final : public td::Actor { public: explicit OpenClose(int cnt) : cnt_(cnt) { } @@ -285,17 +281,17 @@ class OpenClose final : public Actor { yield(); } void wakeup() final { - ObserverBase *observer = reinterpret_cast(123); + auto observer = reinterpret_cast(123); if (cnt_ > 0) { - auto r_file_fd = FileFd::open("server", FileFd::Read | FileFd::Create); + auto r_file_fd = td::FileFd::open("server", td::FileFd::Read | td::FileFd::Create); LOG_CHECK(r_file_fd.is_ok()) << r_file_fd.error(); auto file_fd = r_file_fd.move_as_ok(); - { PollableFd pollable_fd = file_fd.get_poll_info().extract_pollable_fd(observer); } + { auto pollable_fd = file_fd.get_poll_info().extract_pollable_fd(observer); } file_fd.close(); cnt_--; yield(); } else { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } } @@ -304,8 +300,7 @@ class OpenClose final : public Actor { }; TEST(Actors, open_close) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(2); int cnt = 1000000; #if TD_WINDOWS || TD_ANDROID @@ -321,18 +316,18 @@ TEST(Actors, open_close) { } namespace { -class MsgActor : public Actor { +class MsgActor : public td::Actor { public: virtual void msg() = 0; }; -class Slave final : public Actor { +class Slave final : public td::Actor { public: - ActorId msg; - explicit Slave(ActorId msg) : msg(msg) { + td::ActorId msg; + explicit Slave(td::ActorId msg) : msg(msg) { } void hangup() final { - send_closure(msg, &MsgActor::msg); + td::send_closure(msg, &MsgActor::msg); } }; @@ -340,10 +335,10 @@ class MasterActor final : public MsgActor { public: void loop() final { alive_ = true; - slave = create_actor("slave", static_cast>(actor_id(this))); + slave = td::create_actor("slave", static_cast>(actor_id(this))); stop(); } - ActorOwn slave; + td::ActorOwn slave; MasterActor() = default; MasterActor(const MasterActor &) = delete; @@ -356,26 +351,25 @@ class MasterActor final : public MsgActor { void msg() final { CHECK(alive_ == 123456789); } - uint64 alive_ = 123456789; + td::uint64 alive_ = 123456789; }; } // namespace TEST(Actors, call_after_destruct) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - Scheduler scheduler; + td::Scheduler scheduler; scheduler.init(0, {create_queue()}, nullptr); { auto guard = scheduler.get_guard(); - create_actor("Master").release(); + td::create_actor("Master").release(); } - scheduler.run(Timestamp::now()); + scheduler.run(td::Timestamp::in(1)); } -class LinkTokenSlave final : public Actor { +class LinkTokenSlave final : public td::Actor { public: - explicit LinkTokenSlave(ActorShared<> parent) : parent_(std::move(parent)) { + explicit LinkTokenSlave(td::ActorShared<> parent) : parent_(std::move(parent)) { } - void add(uint64 link_token) { + void add(td::uint64 link_token) { CHECK(link_token == get_link_token()); } void close() { @@ -383,42 +377,43 @@ class LinkTokenSlave final : public Actor { } private: - ActorShared<> parent_; + td::ActorShared<> parent_; }; -class LinkTokenMasterActor final : public Actor { +class LinkTokenMasterActor final : public td::Actor { public: explicit LinkTokenMasterActor(int cnt) : cnt_(cnt) { } void start_up() final { - child_ = create_actor("Slave", actor_shared(this, 123)).release(); + child_ = td::create_actor("Slave", actor_shared(this, 123)).release(); yield(); } void loop() final { for (int i = 0; i < 100 && cnt_ > 0; cnt_--, i++) { - auto token = static_cast(cnt_) + 1; + auto token = static_cast(cnt_) + 1; switch (i % 4) { case 0: { - send_closure(ActorShared(child_, token), &LinkTokenSlave::add, token); + td::send_closure(td::ActorShared(child_, token), &LinkTokenSlave::add, token); break; } case 1: { - send_closure_later(ActorShared(child_, token), &LinkTokenSlave::add, token); + td::send_closure_later(td::ActorShared(child_, token), &LinkTokenSlave::add, token); break; } case 2: { - EventCreator::closure(ActorShared(child_, token), &LinkTokenSlave::add, token).try_emit(); + td::EventCreator::closure(td::ActorShared(child_, token), &LinkTokenSlave::add, token) + .try_emit(); break; } case 3: { - EventCreator::closure(ActorShared(child_, token), &LinkTokenSlave::add, token) + td::EventCreator::closure(td::ActorShared(child_, token), &LinkTokenSlave::add, token) .try_emit_later(); break; } } } if (cnt_ == 0) { - send_closure(child_, &LinkTokenSlave::close); + td::send_closure(child_, &LinkTokenSlave::close); } else { yield(); } @@ -426,18 +421,17 @@ class LinkTokenMasterActor final : public Actor { void hangup_shared() final { CHECK(get_link_token() == 123); - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); stop(); } private: int cnt_; - ActorId child_; + td::ActorId child_; }; TEST(Actors, link_token) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(0); auto cnt = 100000; scheduler.create_actor_unsafe(0, "A", cnt).release(); @@ -449,25 +443,25 @@ TEST(Actors, link_token) { TEST(Actors, promise) { int value = -1; - Promise p1 = PromiseCreator::lambda([&](int x) { value = x; }); - p1.set_error(Status::Error("Test error")); + td::Promise p1 = td::PromiseCreator::lambda([&](int x) { value = x; }); + p1.set_error(td::Status::Error("Test error")); ASSERT_EQ(0, value); - Promise p2 = PromiseCreator::lambda([&](Result x) { value = 1; }); - p2.set_error(Status::Error("Test error")); + td::Promise p2 = td::PromiseCreator::lambda([&](td::Result x) { value = 1; }); + p2.set_error(td::Status::Error("Test error")); ASSERT_EQ(1, value); } -class LaterSlave final : public Actor { +class LaterSlave final : public td::Actor { public: - explicit LaterSlave(ActorShared<> parent) : parent_(std::move(parent)) { + explicit LaterSlave(td::ActorShared<> parent) : parent_(std::move(parent)) { } private: - ActorShared<> parent_; + td::ActorShared<> parent_; void hangup() final { sb << "A"; - send_closure(actor_id(this), &LaterSlave::finish); + td::send_closure(actor_id(this), &LaterSlave::finish); } void finish() { sb << "B"; @@ -475,12 +469,12 @@ class LaterSlave final : public Actor { } }; -class LaterMasterActor final : public Actor { +class LaterMasterActor final : public td::Actor { int cnt_ = 3; - std::vector> children_; + td::vector> children_; void start_up() final { for (int i = 0; i < cnt_; i++) { - children_.push_back(create_actor("B", actor_shared(this))); + children_.push_back(td::create_actor("B", actor_shared(this))); } yield(); } @@ -489,16 +483,15 @@ class LaterMasterActor final : public Actor { } void hangup_shared() final { if (!--cnt_) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); stop(); } } }; TEST(Actors, later) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); sb.clear(); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); @@ -508,38 +501,36 @@ TEST(Actors, later) { ASSERT_STREQ(sb.as_cslice().c_str(), "AAABBB"); } -class MultiPromise2 final : public Actor { +class MultiPromise2 final : public td::Actor { public: void start_up() final { - auto promise = PromiseCreator::lambda([](Result result) { + auto promise = td::PromiseCreator::lambda([](td::Result result) { result.ensure(); - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); }); - MultiPromiseActorSafe multi_promise{"MultiPromiseActor2"}; + td::MultiPromiseActorSafe multi_promise{"MultiPromiseActor2"}; multi_promise.add_promise(std::move(promise)); for (int i = 0; i < 10; i++) { - create_actor("Sleep", 0.1, multi_promise.get_promise()).release(); + td::create_actor("Sleep", 0.1, multi_promise.get_promise()).release(); } } }; -class MultiPromise1 final : public Actor { +class MultiPromise1 final : public td::Actor { public: void start_up() final { - auto promise = PromiseCreator::lambda([](Result result) { + auto promise = td::PromiseCreator::lambda([](td::Result result) { CHECK(result.is_error()); - create_actor("B").release(); + td::create_actor("B").release(); }); - MultiPromiseActorSafe multi_promise{"MultiPromiseActor1"}; + td::MultiPromiseActorSafe multi_promise{"MultiPromiseActor1"}; multi_promise.add_promise(std::move(promise)); } }; TEST(Actors, MultiPromise) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - sb.clear(); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); @@ -548,22 +539,20 @@ TEST(Actors, MultiPromise) { scheduler.finish(); } -class FastPromise final : public Actor { +class FastPromise final : public td::Actor { public: void start_up() final { - PromiseFuture pf; + td::PromiseFuture pf; auto promise = pf.move_promise(); auto future = pf.move_future(); promise.set_value(123); CHECK(future.move_as_ok() == 123); - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } }; TEST(Actors, FastPromise) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - sb.clear(); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); @@ -572,20 +561,18 @@ TEST(Actors, FastPromise) { scheduler.finish(); } -class StopInTeardown final : public Actor { +class StopInTeardown final : public td::Actor { void loop() final { stop(); } void tear_down() final { stop(); - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } }; TEST(Actors, stop_in_teardown) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - sb.clear(); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); @@ -594,34 +581,33 @@ TEST(Actors, stop_in_teardown) { scheduler.finish(); } -class AlwaysWaitForMailbox final : public Actor { +class AlwaysWaitForMailbox final : public td::Actor { public: void start_up() final { always_wait_for_mailbox(); - create_actor("Sleep", 0.1, PromiseCreator::lambda([actor_id = actor_id(this), ptr = this](Unit) { - send_closure(actor_id, &AlwaysWaitForMailbox::g); - send_closure(actor_id, &AlwaysWaitForMailbox::g); - CHECK(!ptr->was_f_); - })) + td::create_actor("Sleep", 0.1, + td::PromiseCreator::lambda([actor_id = actor_id(this), ptr = this](td::Unit) { + td::send_closure(actor_id, &AlwaysWaitForMailbox::g); + td::send_closure(actor_id, &AlwaysWaitForMailbox::g); + CHECK(!ptr->was_f_); + })) .release(); } void f() { was_f_ = true; - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } void g() { - send_closure(actor_id(this), &AlwaysWaitForMailbox::f); + td::send_closure(actor_id(this), &AlwaysWaitForMailbox::f); } private: - Timeout timeout_; bool was_f_{false}; }; TEST(Actors, always_wait_for_mailbox) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(0); scheduler.create_actor_unsafe(0, "A").release(); scheduler.start(); @@ -632,17 +618,16 @@ TEST(Actors, always_wait_for_mailbox) { #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED TEST(Actors, send_from_other_threads) { - SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); - ConcurrentScheduler scheduler; + td::ConcurrentScheduler scheduler; scheduler.init(1); int thread_n = 10; - class Listener final : public Actor { + class Listener final : public td::Actor { public: explicit Listener(int cnt) : cnt_(cnt) { } void dec() { if (--cnt_ == 0) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); } } @@ -652,11 +637,11 @@ TEST(Actors, send_from_other_threads) { auto A = scheduler.create_actor_unsafe(1, "A", thread_n).release(); scheduler.start(); - std::vector threads(thread_n); + td::vector threads(thread_n); for (auto &thread : threads) { thread = td::thread([&A, &scheduler] { auto guard = scheduler.get_send_guard(); - send_closure(A, &Listener::dec); + td::send_closure(A, &Listener::dec); }); } while (scheduler.run_main(10)) { @@ -667,3 +652,45 @@ TEST(Actors, send_from_other_threads) { scheduler.finish(); } #endif + +class DelayedCall final : public td::Actor { + public: + void on_called(int *order) { + CHECK(*order == 0); + *order = 1; + } +}; + +class MultiPromiseSendClosureLaterTest final : public td::Actor { + public: + void start_up() final { + delayed_call_ = td::create_actor("DelayedCall").release(); + mpa_.add_promise(td::PromiseCreator::lambda([this](td::Unit) { + CHECK(order_ == 1); + order_++; + td::Scheduler::instance()->finish(); + })); + auto lock = mpa_.get_promise(); + td::send_closure_later(delayed_call_, &DelayedCall::on_called, &order_); + lock.set_value(td::Unit()); + } + + void tear_down() final { + CHECK(order_ == 2); + } + + private: + int order_ = 0; + td::MultiPromiseActor mpa_{"MultiPromiseActor"}; + td::ActorId delayed_call_; +}; + +TEST(Actors, MultiPromiseSendClosureLater) { + td::ConcurrentScheduler scheduler; + scheduler.init(0); + scheduler.create_actor_unsafe(0, "MultiPromiseSendClosureLaterTest").release(); + scheduler.start(); + while (scheduler.run_main(1)) { + } + scheduler.finish(); +} diff --git a/tdactor/test/actors_workers.cpp b/tdactor/test/actors_workers.cpp index bfbe2c90f..172f165a9 100644 --- a/tdactor/test/actors_workers.cpp +++ b/tdactor/test/actors_workers.cpp @@ -12,9 +12,7 @@ namespace { -using namespace td; - -class PowerWorker final : public Actor { +class PowerWorker final : public td::Actor { public: class Callback { public: @@ -27,12 +25,12 @@ class PowerWorker final : public Actor { virtual void on_ready(int query, int res) = 0; virtual void on_closed() = 0; }; - void set_callback(unique_ptr callback) { + void set_callback(td::unique_ptr callback) { callback_ = std::move(callback); } - void task(uint32 x, uint32 p) { - uint32 res = 1; - for (uint32 i = 0; i < p; i++) { + void task(td::uint32 x, td::uint32 p) { + td::uint32 res = 1; + for (td::uint32 i = 0; i < p; i++) { res *= x; } callback_->on_ready(x, res); @@ -43,12 +41,12 @@ class PowerWorker final : public Actor { } private: - unique_ptr callback_; + td::unique_ptr callback_; }; -class Manager final : public Actor { +class Manager final : public td::Actor { public: - Manager(int queries_n, int query_size, std::vector> workers) + Manager(int queries_n, int query_size, td::vector> workers) : workers_(std::move(workers)) , ref_cnt_(static_cast(workers_.size())) , left_query_(queries_n) @@ -57,17 +55,17 @@ class Manager final : public Actor { class Callback final : public PowerWorker::Callback { public: - Callback(ActorId actor_id, int worker_id) : actor_id_(actor_id), worker_id_(worker_id) { + Callback(td::ActorId actor_id, int worker_id) : actor_id_(actor_id), worker_id_(worker_id) { } void on_ready(int query, int result) final { - send_closure(actor_id_, &Manager::on_ready, worker_id_, query, result); + td::send_closure(actor_id_, &Manager::on_ready, worker_id_, query, result); } void on_closed() final { - send_closure_later(actor_id_, &Manager::on_closed, worker_id_); + td::send_closure_later(actor_id_, &Manager::on_closed, worker_id_); } private: - ActorId actor_id_; + td::ActorId actor_id_; int worker_id_; }; @@ -75,9 +73,9 @@ class Manager final : public Actor { int i = 0; for (auto &worker : workers_) { ref_cnt_++; - send_closure_later(worker, &PowerWorker::set_callback, make_unique(actor_id(this), i)); + td::send_closure_later(worker, &PowerWorker::set_callback, td::make_unique(actor_id(this), i)); i++; - send_closure_later(worker, &PowerWorker::task, 3, query_size_); + td::send_closure_later(worker, &PowerWorker::task, 3, query_size_); left_query_--; } } @@ -85,10 +83,10 @@ class Manager final : public Actor { void on_ready(int worker_id, int query, int res) { ref_cnt_--; if (left_query_ == 0) { - send_closure(workers_[worker_id], &PowerWorker::close); + td::send_closure(workers_[worker_id], &PowerWorker::close); } else { ref_cnt_++; - send_closure(workers_[worker_id], &PowerWorker::task, 3, query_size_); + td::send_closure(workers_[worker_id], &PowerWorker::task, 3, query_size_); left_query_--; } } @@ -96,23 +94,23 @@ class Manager final : public Actor { void on_closed(int worker_id) { ref_cnt_--; if (ref_cnt_ == 0) { - Scheduler::instance()->finish(); + td::Scheduler::instance()->finish(); stop(); } } private: - std::vector> workers_; + td::vector> workers_; int ref_cnt_; int left_query_; int query_size_; }; static void test_workers(int threads_n, int workers_n, int queries_n, int query_size) { - ConcurrentScheduler sched; + td::ConcurrentScheduler sched; sched.init(threads_n); - std::vector> workers; + td::vector> workers; for (int i = 0; i < workers_n; i++) { int thread_id = threads_n ? i % (threads_n - 1) + 2 : 0; workers.push_back(sched.create_actor_unsafe(thread_id, PSLICE() << "worker" << i).release()); diff --git a/tddb/td/db/SqliteDb.cpp b/tddb/td/db/SqliteDb.cpp index 8abf5e4ea..e282ce4b9 100644 --- a/tddb/td/db/SqliteDb.cpp +++ b/tddb/td/db/SqliteDb.cpp @@ -175,13 +175,20 @@ Status SqliteDb::set_user_version(int32 version) { return exec(PSLICE() << "PRAGMA user_version = " << version); } -Status SqliteDb::begin_transaction() { +Status SqliteDb::begin_read_transaction() { if (raw_->on_begin()) { return exec("BEGIN"); } return Status::OK(); } +Status SqliteDb::begin_write_transaction() { + if (raw_->on_begin()) { + return exec("BEGIN IMMEDIATE"); + } + return Status::OK(); +} + Status SqliteDb::commit_transaction() { TRY_RESULT(need_commit, raw_->on_commit()); if (need_commit) { diff --git a/tddb/td/db/SqliteDb.h b/tddb/td/db/SqliteDb.h index 022cab151..a6c899cbe 100644 --- a/tddb/td/db/SqliteDb.h +++ b/tddb/td/db/SqliteDb.h @@ -46,7 +46,9 @@ class SqliteDb { Result has_table(Slice table); Result get_pragma(Slice name); Result get_pragma_string(Slice name); - Status begin_transaction() TD_WARN_UNUSED_RESULT; + + Status begin_read_transaction() TD_WARN_UNUSED_RESULT; + Status begin_write_transaction() TD_WARN_UNUSED_RESULT; Status commit_transaction() TD_WARN_UNUSED_RESULT; Result user_version(); diff --git a/tddb/td/db/SqliteKeyValue.h b/tddb/td/db/SqliteKeyValue.h index a10654c52..b44537d48 100644 --- a/tddb/td/db/SqliteKeyValue.h +++ b/tddb/td/db/SqliteKeyValue.h @@ -51,8 +51,11 @@ class SqliteKeyValue { SeqNo erase(Slice key); - Status begin_transaction() TD_WARN_UNUSED_RESULT { - return db_.begin_transaction(); + Status begin_read_transaction() TD_WARN_UNUSED_RESULT { + return db_.begin_read_transaction(); + } + Status begin_write_transaction() TD_WARN_UNUSED_RESULT { + return db_.begin_write_transaction(); } Status commit_transaction() TD_WARN_UNUSED_RESULT { return db_.commit_transaction(); diff --git a/tddb/td/db/SqliteKeyValueAsync.cpp b/tddb/td/db/SqliteKeyValueAsync.cpp index 5f594e488..3f59b2b81 100644 --- a/tddb/td/db/SqliteKeyValueAsync.cpp +++ b/tddb/td/db/SqliteKeyValueAsync.cpp @@ -121,7 +121,7 @@ class SqliteKeyValueAsync final : public SqliteKeyValueAsyncInterface { wakeup_at_ = 0; cnt_ = 0; - kv_->begin_transaction().ensure(); + kv_->begin_write_transaction().ensure(); for (auto &it : buffer_) { if (it.second) { kv_->set(it.first, it.second.value()); diff --git a/tdutils/td/utils/port/uname.cpp b/tdutils/td/utils/port/uname.cpp index 6eea32bed..327632821 100644 --- a/tdutils/td/utils/port/uname.cpp +++ b/tdutils/td/utils/port/uname.cpp @@ -150,7 +150,9 @@ Slice get_operating_system_version() { } var clientStrings = [ - {s:'Windows 10', r:/(Windows 10.0|Windows NT 10.0)/}, + {s:'Windows 11', r:/(Windows 11|Windows NT 11)/}, + // there is no way to distinguish Windows 10 from newer versions, so report it as just Windows. + // {s:'Windows 10 or later', r:/(Windows 10|Windows NT 10)/}, {s:'Windows 8.1', r:/(Windows 8.1|Windows NT 6.3)/}, {s:'Windows 8', r:/(Windows 8|Windows NT 6.2)/}, {s:'Windows 7', r:/(Windows 7|Windows NT 6.1)/}, @@ -242,7 +244,18 @@ Slice get_operating_system_version() { if (major == 10) { if (is_server) { - return os_version_info.dwBuildNumber >= 17623 ? "Windows Server 2019" : "Windows Server 2016"; + if (os_version_info.dwBuildNumber >= 20201) { + // https://techcommunity.microsoft.com/t5/windows-server-insiders/announcing/m-p/1614436 + return "Windows Server 2022"; + } + if (os_version_info.dwBuildNumber >= 17623) { + // https://techcommunity.microsoft.com/t5/windows-server-insiders/announcing/m-p/173715 + return "Windows Server 2019"; + } + return "Windows Server 2016"; + } + if (os_version_info.dwBuildNumber >= 21900) { // build numbers between 21391 and 21999 aren't used + return "Windows 11"; } return "Windows 10"; } diff --git a/tdutils/test/EpochBasedMemoryReclamation.cpp b/tdutils/test/EpochBasedMemoryReclamation.cpp index d9bf3c322..66131545e 100644 --- a/tdutils/test/EpochBasedMemoryReclamation.cpp +++ b/tdutils/test/EpochBasedMemoryReclamation.cpp @@ -58,7 +58,7 @@ TEST(EpochBaseMemoryReclamation, stress) { for (auto &thread : threads) { thread.join(); } - LOG(ERROR) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe(); + LOG(INFO) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe(); //CHECK(static_cast(ebmr.to_delete_size_unsafe()) <= threads_n * threads_n); for (int i = 0; i < threads_n; i++) { ebmr.get_locker(i).retire_sync(); diff --git a/tdutils/test/HazardPointers.cpp b/tdutils/test/HazardPointers.cpp index a23e18fb4..9b6b9a81e 100644 --- a/tdutils/test/HazardPointers.cpp +++ b/tdutils/test/HazardPointers.cpp @@ -50,7 +50,7 @@ TEST(HazardPointers, stress) { for (auto &thread : threads) { thread.join(); } - LOG(ERROR) << "Undeleted pointers: " << hazard_pointers.to_delete_size_unsafe(); + LOG(INFO) << "Undeleted pointers: " << hazard_pointers.to_delete_size_unsafe(); CHECK(static_cast(hazard_pointers.to_delete_size_unsafe()) <= threads_n * threads_n); for (int i = 0; i < threads_n; i++) { hazard_pointers.retire(i); diff --git a/tdutils/test/buffer.cpp b/tdutils/test/buffer.cpp index 403af89b8..8c5d7eb02 100644 --- a/tdutils/test/buffer.cpp +++ b/tdutils/test/buffer.cpp @@ -9,47 +9,45 @@ #include "td/utils/buffer.h" #include "td/utils/Random.h" -using namespace td; - TEST(Buffer, buffer_builder) { { - BufferBuilder builder; + td::BufferBuilder builder; builder.append("b"); builder.prepend("a"); builder.append("c"); ASSERT_EQ(builder.extract().as_slice(), "abc"); } { - BufferBuilder builder{"hello", 0, 0}; + td::BufferBuilder builder{"hello", 0, 0}; ASSERT_EQ(builder.extract().as_slice(), "hello"); } { - BufferBuilder builder{"hello", 1, 1}; + td::BufferBuilder builder{"hello", 1, 1}; builder.prepend("A "); builder.append(" B"); ASSERT_EQ(builder.extract().as_slice(), "A hello B"); } { - std::string str = rand_string('a', 'z', 10000); - auto splitted_str = rand_split(str); + auto str = td::rand_string('a', 'z', 10000); + auto splitted_str = td::rand_split(str); - int l = Random::fast(0, static_cast(splitted_str.size() - 1)); + int l = td::Random::fast(0, static_cast(splitted_str.size() - 1)); int r = l; - BufferBuilder builder(splitted_str[l], 123, 1000); - while (l != 0 || r != static_cast(splitted_str.size()) - 1) { - if (l == 0 || (Random::fast_bool() && r != static_cast(splitted_str.size() - 1))) { + td::BufferBuilder builder(splitted_str[l], 123, 1000); + while (l != 0 || r != static_cast(splitted_str.size()) - 1) { + if (l == 0 || (td::Random::fast_bool() && r != static_cast(splitted_str.size() - 1))) { r++; - if (Random::fast_bool()) { + if (td::Random::fast_bool()) { builder.append(splitted_str[r]); } else { - builder.append(BufferSlice(splitted_str[r])); + builder.append(td::BufferSlice(splitted_str[r])); } } else { l--; - if (Random::fast_bool()) { + if (td::Random::fast_bool()) { builder.prepend(splitted_str[l]); } else { - builder.prepend(BufferSlice(splitted_str[l])); + builder.prepend(td::BufferSlice(splitted_str[l])); } } } diff --git a/tdutils/test/json.cpp b/tdutils/test/json.cpp index e7e986a4e..f374a233d 100644 --- a/tdutils/test/json.cpp +++ b/tdutils/test/json.cpp @@ -12,17 +12,15 @@ #include -using namespace td; - -static void decode_encode(string str, string result = "") { +static void decode_encode(td::string str, td::string result = "") { auto str_copy = str; - auto r_value = json_decode(str_copy); + auto r_value = td::json_decode(str_copy); ASSERT_TRUE(r_value.is_ok()); if (r_value.is_error()) { LOG(INFO) << r_value.error(); return; } - auto new_str = json_encode(r_value.ok()); + auto new_str = td::json_encode(r_value.ok()); if (result.empty()) { result = str; } @@ -31,18 +29,19 @@ static void decode_encode(string str, string result = "") { TEST(JSON, array) { char tmp[1000]; - StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); - JsonBuilder jb(std::move(sb)); + td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)}); + td::JsonBuilder jb(std::move(sb)); jb.enter_value().enter_array() << "Hello" << -123; ASSERT_EQ(jb.string_builder().is_error(), false); auto encoded = jb.string_builder().as_cslice().str(); ASSERT_EQ("[\"Hello\",-123]", encoded); decode_encode(encoded); } + TEST(JSON, object) { char tmp[1000]; - StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); - JsonBuilder jb(std::move(sb)); + td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)}); + td::JsonBuilder jb(std::move(sb)); auto c = jb.enter_object(); c("key", "value"); c("1", 2); @@ -55,8 +54,8 @@ TEST(JSON, object) { TEST(JSON, nested) { char tmp[1000]; - StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); - JsonBuilder jb(std::move(sb)); + td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)}); + td::JsonBuilder jb(std::move(sb)); { auto a = jb.enter_array(); a << 1; diff --git a/tdutils/test/pq.cpp b/tdutils/test/pq.cpp index a59134a0b..9c0d18555 100644 --- a/tdutils/test/pq.cpp +++ b/tdutils/test/pq.cpp @@ -18,11 +18,9 @@ #include #include -using namespace td; - #if TD_HAVE_OPENSSL -static bool is_prime(uint64 x) { - for (uint64 d = 2; d < x && d * d <= x; d++) { +static bool is_prime(td::uint64 x) { + for (td::uint64 d = 2; d < x && d * d <= x; d++) { if (x % d == 0) { return false; } @@ -30,8 +28,8 @@ static bool is_prime(uint64 x) { return true; } -static std::vector gen_primes(uint64 L, uint64 R, int limit = 0) { - std::vector res; +static td::vector gen_primes(td::uint64 L, td::uint64 R, int limit = 0) { + td::vector res; for (auto x = L; x <= R && (limit <= 0 || res.size() < static_cast(limit)); x++) { if (is_prime(x)) { res.push_back(x); @@ -40,21 +38,23 @@ static std::vector gen_primes(uint64 L, uint64 R, int limit = 0) { return res; } -static std::vector gen_primes() { - std::vector result; - append(result, gen_primes(1, 100)); - append(result, gen_primes((1ull << 31) - 500000, std::numeric_limits::max(), 5)); - append(result, gen_primes((1ull << 32) - 500000, std::numeric_limits::max(), 5)); - append(result, gen_primes((1ull << 39) - 500000, std::numeric_limits::max(), 1)); +static td::vector gen_primes() { + td::vector result; + td::append(result, gen_primes(1, 100)); + td::append(result, gen_primes((1ull << 31) - 500000, std::numeric_limits::max(), 5)); + td::append(result, gen_primes((1ull << 32) - 500000, std::numeric_limits::max(), 5)); + td::append(result, gen_primes((1ull << 39) - 500000, std::numeric_limits::max(), 1)); return result; } -using PqQuery = std::pair; +using PqQuery = std::pair; + static bool cmp(const PqQuery &a, const PqQuery &b) { return a.first * a.second < b.first * b.second; } -static std::vector gen_pq_queries() { - std::vector res; + +static td::vector gen_pq_queries() { + td::vector res; auto primes = gen_primes(); for (auto q : primes) { for (auto p : primes) { @@ -68,21 +68,21 @@ static std::vector gen_pq_queries() { return res; } -static void test_pq(uint64 first, uint64 second) { - BigNum p = BigNum::from_decimal(PSLICE() << first).move_as_ok(); - BigNum q = BigNum::from_decimal(PSLICE() << second).move_as_ok(); +static void test_pq(td::uint64 first, td::uint64 second) { + td::BigNum p = td::BigNum::from_decimal(PSLICE() << first).move_as_ok(); + td::BigNum q = td::BigNum::from_decimal(PSLICE() << second).move_as_ok(); - BigNum pq; - BigNumContext context; - BigNum::mul(pq, p, q, context); - std::string pq_str = pq.to_binary(); + td::BigNum pq; + td::BigNumContext context; + td::BigNum::mul(pq, p, q, context); + td::string pq_str = pq.to_binary(); - std::string p_str, q_str; + td::string p_str, q_str; int err = td::pq_factorize(pq_str, &p_str, &q_str); LOG_CHECK(err == 0) << first << " * " << second; - BigNum p_res = BigNum::from_binary(p_str); - BigNum q_res = BigNum::from_binary(q_str); + td::BigNum p_res = td::BigNum::from_binary(p_str); + td::BigNum q_res = td::BigNum::from_binary(q_str); LOG_CHECK(p_str == p.to_binary()) << td::tag("got", p_res.to_decimal()) << td::tag("expected", first); LOG_CHECK(q_str == q.to_binary()) << td::tag("got", q_res.to_decimal()) << td::tag("expected", second);