Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2021-10-15 22:50:34 +02:00
commit 982b994332
63 changed files with 1084 additions and 1128 deletions

View File

@ -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) project(TdExample VERSION 1.0 LANGUAGES CXX)

View File

@ -803,8 +803,8 @@ foundMessages total_count:int32 messages:vector<message> next_offset:string = Fo
//@description Describes a sponsored message @id Unique sponsored message identifier @sponsor_chat_id Chat identifier //@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 //@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 start_parameter:string content:MessageContent = SponsoredMessage; sponsoredMessage id:int32 sponsor_chat_id:int53 link:InternalLinkType content:MessageContent = SponsoredMessage;
//@description Contains a list of sponsored messages @messages List of sponsored messages //@description Contains a list of sponsored messages @messages List of sponsored messages
sponsoredMessages messages:vector<sponsoredMessage> = SponsoredMessages; sponsoredMessages messages:vector<sponsoredMessage> = 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 //@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; 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 //@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<datedFile> = IdentityDocument; identityDocument number:string expiry_date:date front_side:datedFile reverse_side:datedFile selfie:datedFile translation:vector<datedFile> = 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 //@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<InputFile> = InputIdentityDocument; inputIdentityDocument number:string expiry_date:date front_side:InputFile reverse_side:InputFile selfie:InputFile translation:vector<InputFile> = InputIdentityDocument;

View File

@ -1,5 +1,11 @@
cmake_minimum_required(VERSION 3.0 FATAL_ERROR) 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) 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) set(SOURCES crc32.h crc32.c tlc.c tl-parser.c tl-parser.h tl-parser-tree.h tl-tl.h portable_endian.h)

View File

@ -703,9 +703,7 @@ void AnimationsManager::add_saved_animation(const tl_object_ptr<td_api::InputFil
} }
void AnimationsManager::send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise) { void AnimationsManager::send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
// TODO invokeAfter and log event // TODO invokeAfter and log event
auto file_view = td_->file_manager_->get_file_view(animation_id); auto file_view = td_->file_manager_->get_file_view(animation_id);

View File

@ -472,9 +472,8 @@ Result<string> BackgroundManager::get_background_url(const string &name,
void BackgroundManager::reload_background_from_server( void BackgroundManager::reload_background_from_server(
BackgroundId background_id, const string &background_name, BackgroundId background_id, const string &background_name,
telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper, Promise<Unit> &&promise) const { telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper, Promise<Unit> &&promise) const {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
td_->create_handler<GetBackgroundQuery>(std::move(promise)) td_->create_handler<GetBackgroundQuery>(std::move(promise))
->send(background_id, background_name, std::move(input_wallpaper)); ->send(background_id, background_name, std::move(input_wallpaper));
} }

View File

@ -840,7 +840,7 @@ void CallActor::send_with_promise(NetQueryPtr query, Promise<NetQueryPtr> promis
void CallActor::hangup() { void CallActor::hangup() {
container_.for_each( container_.for_each(
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); [](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Global::request_aborted_error()); });
stop(); stop();
} }

View File

@ -274,9 +274,7 @@ void CallbackQueriesManager::send_get_callback_answer_query(
FullMessageId full_message_id, tl_object_ptr<td_api::CallbackQueryPayload> &&payload, FullMessageId full_message_id, tl_object_ptr<td_api::CallbackQueryPayload> &&payload,
tl_object_ptr<telegram_api::InputCheckPasswordSRP> &&password, tl_object_ptr<telegram_api::InputCheckPasswordSRP> &&password,
Promise<td_api::object_ptr<td_api::callbackQueryAnswer>> &&promise) { Promise<td_api::object_ptr<td_api::callbackQueryAnswer>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto dialog_id = full_message_id.get_dialog_id(); auto dialog_id = full_message_id.get_dialog_id();
if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) { if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {

View File

@ -956,9 +956,7 @@ void ConfigManager::lazy_request_config() {
} }
void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>> &&promise) { void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get(); auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
if (auth_manager != nullptr && auth_manager->is_bot()) { if (auth_manager != nullptr && auth_manager->is_bot()) {
@ -974,9 +972,7 @@ void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>
} }
void ConfigManager::get_content_settings(Promise<Unit> &&promise) { void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get(); auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) { if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) {
@ -991,9 +987,7 @@ void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
} }
void ConfigManager::set_content_settings(bool ignore_sensitive_content_restrictions, Promise<Unit> &&promise) { void ConfigManager::set_content_settings(bool ignore_sensitive_content_restrictions, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
last_set_content_settings_ = ignore_sensitive_content_restrictions; last_set_content_settings_ = ignore_sensitive_content_restrictions;
auto &queries = set_content_settings_queries_[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<Unit> &&promise) { void ConfigManager::get_global_privacy_settings(Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get(); auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) { if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) {
@ -1028,9 +1020,8 @@ void ConfigManager::get_global_privacy_settings(Promise<Unit> &&promise) {
} }
void ConfigManager::set_archive_and_mute(bool archive_and_mute, Promise<Unit> &&promise) { void ConfigManager::set_archive_and_mute(bool archive_and_mute, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (archive_and_mute) { if (archive_and_mute) {
remove_suggested_action(suggested_actions_, SuggestedAction{SuggestedAction::Type::EnableArchiveAndMuteNewChats}); remove_suggested_action(suggested_actions_, SuggestedAction{SuggestedAction::Type::EnableArchiveAndMuteNewChats});
} }

View File

@ -1185,13 +1185,11 @@ class TogglePrehistoryHiddenQuery final : public Td::ResultHandler {
td->updates_manager_->on_get_updates( td->updates_manager_->on_get_updates(
std::move(ptr), 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 { is_all_history_available = is_all_history_available_](Unit result) mutable {
if (G()->close_flag()) { send_closure(actor_id, &ContactsManager::on_update_channel_is_all_history_available, channel_id,
return promise.set_error(Status::Error(500, "Request aborted")); is_all_history_available, std::move(promise));
}
send_closure(G()->contacts_manager(), &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); LOG(INFO) << "Receive result for ToggleSlowModeQuery: " << to_string(ptr);
td->updates_manager_->on_get_updates( td->updates_manager_->on_get_updates(
std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_, std::move(ptr),
slow_mode_delay = slow_mode_delay_](Unit result) mutable { PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_),
if (G()->close_flag()) { channel_id = channel_id_, slow_mode_delay = slow_mode_delay_](Unit result) mutable {
return promise.set_error(Status::Error(500, "Request aborted")); send_closure(actor_id, &ContactsManager::on_update_channel_slow_mode_delay, channel_id, slow_mode_delay,
} std::move(promise));
send_closure(G()->contacts_manager(), &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<Unit> &&promise) { void ContactsManager::add_contact(Contact contact, bool share_phone_number, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (!are_contacts_loaded_) { if (!are_contacts_loaded_) {
load_contacts(PromiseCreator::lambda([actor_id = actor_id(this), contact = std::move(contact), share_phone_number, 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"; LOG(INFO) << "Successfully loaded " << all_imported_contacts_.size() << " imported contacts from database";
} }
load_imported_contact_users_multipromise_.add_promise(PromiseCreator::lambda([](Result<> result) { load_imported_contact_users_multipromise_.add_promise(
if (result.is_ok()) { PromiseCreator::lambda([actor_id = actor_id(this)](Result<Unit> result) {
send_closure_later(G()->contacts_manager(), &ContactsManager::on_load_imported_contacts_finished); 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(); auto lock_promise = load_imported_contact_users_multipromise_.get_promise();
@ -5729,9 +5724,7 @@ std::pair<int32, vector<UserId>> ContactsManager::search_contacts(const string &
} }
void ContactsManager::share_phone_number(UserId user_id, Promise<Unit> &&promise) { void ContactsManager::share_phone_number(UserId user_id, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (!are_contacts_loaded_) { if (!are_contacts_loaded_) {
load_contacts(PromiseCreator::lambda( 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()); CHECK(uploaded_profile_photos_.find(file_id) == uploaded_profile_photos_.end());
uploaded_profile_photos_.emplace( uploaded_profile_photos_.emplace(
file_id, UploadedProfilePhoto{main_frame_timestamp, is_animation, reupload_count, std::move(promise)}); 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 // 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); 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, void ContactsManager::get_channel_statistics_dc_id_impl(ChannelId channel_id, bool for_full_statistics,
Promise<DcId> &&promise) { Promise<DcId> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto channel_full = get_channel_full(channel_id, false, "get_channel_statistics_dc_id_impl"); auto channel_full = get_channel_full(channel_id, false, "get_channel_statistics_dc_id_impl");
if (channel_full == nullptr) { 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, void ContactsManager::send_get_channel_stats_query(DcId dc_id, ChannelId channel_id, bool is_dark,
Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise) { Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
const Channel *c = get_channel(channel_id); const Channel *c = get_channel(channel_id);
CHECK(c != nullptr); CHECK(c != nullptr);
if (c->is_megagroup) { 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( void ContactsManager::send_get_channel_message_stats_query(
DcId dc_id, FullMessageId full_message_id, bool is_dark, DcId dc_id, FullMessageId full_message_id, bool is_dark,
Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise) { Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto dialog_id = full_message_id.get_dialog_id(); 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")) { 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, void ContactsManager::send_load_async_graph_query(DcId dc_id, string token, int64 x,
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise) { Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
td_->create_handler<LoadAsyncGraphQuery>(std::move(promise))->send(token, x, dc_id); td_->create_handler<LoadAsyncGraphQuery>(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( void ContactsManager::transfer_channel_ownership(
ChannelId channel_id, UserId user_id, tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password, ChannelId channel_id, UserId user_id, tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
td_->create_handler<EditChannelCreatorQuery>(std::move(promise)) td_->create_handler<EditChannelCreatorQuery>(std::move(promise))
->send(channel_id, user_id, std::move(input_check_password)); ->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, void ContactsManager::export_dialog_invite_link_impl(DialogId dialog_id, int32 expire_date, int32 usage_limit,
bool is_permanent, bool is_permanent,
Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) { Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id)); TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
td_->create_handler<ExportChatInviteQuery>(std::move(promise)) td_->create_handler<ExportChatInviteQuery>(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, void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
DialogParticipantStatus status, DialogParticipantStatus old_status, DialogParticipantStatus status, DialogParticipantStatus old_status,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
LOG(INFO) << "Restrict " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to " LOG(INFO) << "Restrict " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to "
<< status; << status;
const Channel *c = get_channel(channel_id); 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()) { if (old_status.is_member() && !status.is_member() && !status.is_banned()) {
// we can't make participant Left without kicking it first // we can't make participant Left without kicking it first
auto on_result_promise = PromiseCreator::lambda([channel_id, participant_dialog_id, status, auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, participant_dialog_id,
promise = std::move(promise)](Result<> result) mutable { status, promise = std::move(promise)](Result<> result) mutable {
if (result.is_error()) { if (result.is_error()) {
return promise.set_error(result.move_as_error()); return promise.set_error(result.move_as_error());
} }
create_actor<SleepActor>("RestrictChannelParticipantSleepActor", 1.0, create_actor<SleepActor>("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 { promise = std::move(promise)](Result<> result) mutable {
if (result.is_error()) { if (result.is_error()) {
return promise.set_error(result.move_as_error()); return promise.set_error(result.move_as_error());
} }
send_closure(G()->contacts_manager(), &ContactsManager::restrict_channel_participant, send_closure(actor_id, &ContactsManager::restrict_channel_participant, channel_id,
channel_id, participant_dialog_id, status, participant_dialog_id, status, DialogParticipantStatus::Banned(0),
DialogParticipantStatus::Banned(0), std::move(promise)); std::move(promise));
})) }))
.release(); .release();
}); });
@ -7969,10 +7953,10 @@ void ContactsManager::on_load_contacts_from_database(string value) {
LOG(INFO) << "Successfully loaded " << user_ids.size() << " contacts from database"; LOG(INFO) << "Successfully loaded " << user_ids.size() << " contacts from database";
load_contact_users_multipromise_.add_promise( load_contact_users_multipromise_.add_promise(PromiseCreator::lambda(
PromiseCreator::lambda([expected_contact_count = user_ids.size()](Result<> result) { [actor_id = actor_id(this), expected_contact_count = user_ids.size()](Result<Unit> result) {
if (result.is_ok()) { 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) { if (u->is_name_changed) {
td_->messages_manager_->on_dialog_title_updated(DialogId(user_id)); auto messages_manager = td_->messages_manager_.get();
for_each_secret_chat_with_user(user_id, messages_manager->on_dialog_title_updated(DialogId(user_id));
[messages_manager = td_->messages_manager_.get()](SecretChatId secret_chat_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)); messages_manager->on_dialog_title_updated(DialogId(secret_chat_id));
}); });
} }
if (u->is_photo_changed) { if (u->is_photo_changed) {
td_->messages_manager_->on_dialog_photo_updated(DialogId(user_id)); auto messages_manager = td_->messages_manager_.get();
for_each_secret_chat_with_user(user_id, messages_manager->on_dialog_photo_updated(DialogId(user_id));
[messages_manager = td_->messages_manager_.get()](SecretChatId secret_chat_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)); messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id));
}); });
} }
if (u->is_status_changed && user_id != get_my_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(); 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<telegram_api::ChatFull> &&c
if (chat->groupcall_default_join_as_ != nullptr) { if (chat->groupcall_default_join_as_ != nullptr) {
default_join_group_call_as_dialog_id = DialogId(chat->groupcall_default_join_as_); 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(), send_closure_later(G()->messages_manager(),
&MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(chat_id), &MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(chat_id),
default_join_group_call_as_dialog_id, false); default_join_group_call_as_dialog_id, false);
@ -10653,7 +10637,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
if (channel->groupcall_default_join_as_ != nullptr) { if (channel->groupcall_default_join_as_ != nullptr) {
default_join_group_call_as_dialog_id = DialogId(channel->groupcall_default_join_as_); 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(), send_closure_later(G()->messages_manager(),
&MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(channel_id), &MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(channel_id),
default_join_group_call_as_dialog_id, false); 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, ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit, string additional_query,
int32 additional_limit, tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants, int32 additional_limit, tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
Promise<DialogParticipants> &&promise) { Promise<DialogParticipants> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
on_get_users(std::move(channel_participants->users_), "on_get_channel_participants"); on_get_users(std::move(channel_participants->users_), "on_get_channel_participants");
on_get_chats(std::move(channel_participants->chats_), "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, void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay"); auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay");
if (channel_full != nullptr) { if (channel_full != nullptr) {
on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0); 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, void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
CHECK(channel_id.is_valid()); CHECK(channel_id.is_valid());
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_is_all_history_available"); 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) { 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, void ContactsManager::finish_get_dialog_participant(DialogParticipant &&dialog_participant,
Promise<td_api::object_ptr<td_api::chatMember>> &&promise) { Promise<td_api::object_ptr<td_api::chatMember>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto participant_dialog_id = dialog_participant.dialog_id; auto participant_dialog_id = dialog_participant.dialog_id;
bool is_user = participant_dialog_id.get_type() == DialogType::User; 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, void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id,
Promise<DialogParticipant> &&promise) { Promise<DialogParticipant> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
const auto *participant = get_chat_participant(chat_id, user_id); const auto *participant = get_chat_participant(chat_id, user_id);
if (participant == nullptr) { 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, void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &query, int32 limit,
DialogParticipantsFilter filter, DialogParticipantsFilter filter,
Promise<DialogParticipants> &&promise) { Promise<DialogParticipants> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto chat_full = get_chat_full(chat_id); auto chat_full = get_chat_full(chat_id);
if (chat_full == nullptr) { 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, void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
Promise<DialogParticipant> &&promise) { Promise<DialogParticipant> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
LOG(INFO) << "Receive a member " << dialog_participant.dialog_id << " of a channel " << channel_id; 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"}; MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"};
load_users_multipromise.add_promise( load_users_multipromise.add_promise(
PromiseCreator::lambda([dialog_id, administrators, promise = std::move(promise)](Result<> result) mutable { PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, administrators,
send_closure(G()->contacts_manager(), &ContactsManager::on_load_administrator_users_finished, dialog_id, promise = std::move(promise)](Result<Unit> result) mutable {
send_closure(actor_id, &ContactsManager::on_load_administrator_users_finished, dialog_id,
std::move(administrators), std::move(result), std::move(promise)); 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, void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id,
vector<DialogAdministrator> administrators, Result<> result, vector<DialogAdministrator> administrators, Result<> result,
Promise<Unit> promise) { Promise<Unit> promise) {
if (result.is_ok()) { if (!G()->close_flag() && result.is_ok()) {
dialog_administrators_.emplace(dialog_id, std::move(administrators)); dialog_administrators_.emplace(dialog_id, std::move(administrators));
} }
promise.set_value(Unit()); 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<telegram_api::InputFile> input_file) { void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) {
LOG(INFO) << "File " << file_id << " has been uploaded";
auto it = uploaded_profile_photos_.find(file_id); auto it = uploaded_profile_photos_.find(file_id);
CHECK(it != uploaded_profile_photos_.end()); CHECK(it != uploaded_profile_photos_.end());
@ -15773,6 +15743,8 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<tele
uploaded_profile_photos_.erase(it); uploaded_profile_photos_.erase(it);
LOG(INFO) << "Uploaded " << (is_animation ? "animated" : "static") << " profile photo " << file_id
<< " with reupload_count = " << reupload_count;
FileView file_view = td_->file_manager_->get_file_view(file_id); FileView file_view = td_->file_manager_->get_file_view(file_id);
if (file_view.has_remote_location() && input_file == nullptr) { if (file_view.has_remote_location() && input_file == nullptr) {
if (file_view.main_remote_location().is_web()) { if (file_view.main_remote_location().is_web()) {
@ -15785,8 +15757,10 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<tele
// delete file reference and forcely reupload the file // delete file reference and forcely reupload the file
if (is_animation) { if (is_animation) {
CHECK(file_view.get_type() == FileType::Animation); CHECK(file_view.get_type() == FileType::Animation);
LOG_CHECK(file_view.main_remote_location().is_common()) << file_view.main_remote_location();
} else { } else {
CHECK(file_view.get_type() == FileType::Photo); CHECK(file_view.get_type() == FileType::Photo);
LOG_CHECK(file_view.main_remote_location().is_photo()) << file_view.main_remote_location();
} }
auto file_reference = auto file_reference =
is_animation ? FileManager::extract_file_reference(file_view.main_remote_location().as_input_document()) is_animation ? FileManager::extract_file_reference(file_view.main_remote_location().as_input_document())

View File

@ -59,7 +59,7 @@ void DelayDispatcher::tear_down() {
while (!queue_.empty()) { while (!queue_.empty()) {
auto query = std::move(queue_.front()); auto query = std::move(queue_.front());
queue_.pop(); queue_.pop();
query.net_query->set_error(Status::Error(500, "Request aborted")); query.net_query->set_error(Global::request_aborted_error());
send_closure(std::move(query.callback), &NetQueryCallback::on_result, std::move(query.net_query)); send_closure(std::move(query.callback), &NetQueryCallback::on_result, std::move(query.net_query));
} }
parent_.reset(); parent_.reset();

View File

@ -288,8 +288,11 @@ class DialogDbImpl final : public DialogDbSyncInterface {
return std::move(notification_groups); return std::move(notification_groups);
} }
Status begin_transaction() final { Status begin_read_transaction() final {
return db_.begin_transaction(); return db_.begin_read_transaction();
}
Status begin_write_transaction() final {
return db_.begin_write_transaction();
} }
Status commit_transaction() final { Status commit_transaction() final {
return db_.commit_transaction(); return db_.commit_transaction();
@ -463,7 +466,7 @@ class DialogDbAsync final : public DialogDbAsyncInterface {
if (pending_writes_.empty()) { if (pending_writes_.empty()) {
return; return;
} }
sync_db_->begin_transaction().ensure(); sync_db_->begin_write_transaction().ensure();
for (auto &query : pending_writes_) { for (auto &query : pending_writes_) {
query.set_value(Unit()); query.set_value(Unit());
} }

View File

@ -55,7 +55,8 @@ class DialogDbSyncInterface {
virtual Result<int32> get_secret_chat_count(FolderId folder_id) = 0; virtual Result<int32> 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; virtual Status commit_transaction() = 0;
}; };

View File

@ -227,28 +227,17 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source
auto &node = nodes_[dest.node_id]; auto &node = nodes_[dest.node_id];
node.query->active_queries++; node.query->active_queries++;
auto promise = PromiseCreator::lambda([dest, file_source_id, file_reference_manager = G()->file_reference_manager(), auto promise = PromiseCreator::lambda([dest, file_source_id, actor_id = actor_id(this),
file_manager = G()->file_manager()](Result<Unit> result) { file_manager_actor_id = G()->file_manager()](Result<Unit> result) {
if (G()->close_flag()) { auto new_promise = PromiseCreator::lambda([dest, file_source_id, actor_id](Result<Unit> result) {
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<Unit> result) {
if (G()->close_flag()) {
VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing";
return;
}
Status status; Status status;
if (result.is_error()) { if (result.is_error()) {
status = result.move_as_error(); status = result.move_as_error();
} }
send_closure(file_reference_manager, &FileReferenceManager::on_query_result, dest, file_source_id, send_closure(actor_id, &FileReferenceManager::on_query_result, dest, file_source_id, std::move(status), 0);
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)); std::move(result), std::move(new_promise));
}); });
auto index = static_cast<size_t>(file_source_id.get()) - 1; auto index = static_cast<size_t>(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 FileSourceWallpapers &source) { promise.set_error(Status::Error("Can't repair old wallpapers")); },
[&](const FileSourceWebPage &source) { [&](const FileSourceWebPage &source) {
send_closure_later(G()->web_pages_manager(), &WebPagesManager::reload_web_page_by_url, source.url, 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<WebPageId> &&result) mutable {
if (result.is_error()) {
promise.set_error(result.move_as_error());
} else {
promise.set_value(Unit());
}
}));
}, },
[&](const FileSourceSavedAnimations &source) { [&](const FileSourceSavedAnimations &source) {
send_closure_later(G()->animations_manager(), &AnimationsManager::repair_saved_animations, std::move(promise)); 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, FileReferenceManager::Destination FileReferenceManager::on_query_result(Destination dest, FileSourceId file_source_id,
Status status, int32 sub) { 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 VLOG(file_references) << "Receive result of file reference repair query for file " << dest.node_id
<< " with generation " << dest.generation << " from " << file_source_id << ": " << status << " " << " with generation " << dest.generation << " from " << file_source_id << ": " << status << " "
<< sub; << sub;

View File

@ -383,6 +383,10 @@ class Global final : public ActorContext {
#endif #endif
} }
static Status request_aborted_error() {
return Status::Error(500, "Request aborted");
}
void set_close_flag() { void set_close_flag() {
close_flag_ = true; close_flag_ = true;
} }
@ -390,6 +394,10 @@ class Global final : public ActorContext {
return close_flag_.load(); return close_flag_.load();
} }
Status close_status() const {
return close_flag() ? request_aborted_error() : Status::OK();
}
bool is_expected_error(const Status &error) const { bool is_expected_error(const Status &error) const {
CHECK(error.is_error()); CHECK(error.is_error());
if (error.code() == 401) { if (error.code() == 401) {

View File

@ -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, void GroupCallManager::on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id,
Promise<GroupCallId> &&promise) { Promise<GroupCallId> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (!input_group_call_id.is_valid()) { if (!input_group_call_id.is_valid()) {
return promise.set_error(Status::Error(500, "Receive invalid group call identifier")); 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); load_group_call_queries_.erase(it);
if (G()->close_flag()) { if (G()->close_flag()) {
result = Status::Error(500, "Request aborted"); result = Global::request_aborted_error();
} }
if (result.is_ok()) { if (result.is_ok()) {
@ -2351,10 +2349,7 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id,
int32 channel_id, int32 channel_id,
td_api::object_ptr<td_api::GroupCallVideoQuality> quality, td_api::object_ptr<td_api::GroupCallVideoQuality> quality,
Promise<string> &&promise) { Promise<string> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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<Unit> &&promise) { void GroupCallManager::start_scheduled_group_call(GroupCallId group_call_id, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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<Unit> &&promise) { void GroupCallManager::set_group_call_title(GroupCallId group_call_id, string title, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::toggle_group_call_is_my_video_paused(GroupCallId group_call_id, bool is_my_video_paused,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::toggle_group_call_is_my_video_enabled(GroupCallId group_call_id, bool is_my_video_enabled,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::toggle_group_call_is_my_presentation_paused(GroupCallId group_call_id,
bool is_my_presentation_paused, bool is_my_presentation_paused,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::toggle_group_call_start_subscribed(GroupCallId group_call_id, bool start_subscribed,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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<Unit> &&promise) { void GroupCallManager::revoke_group_call_invite_link(GroupCallId group_call_id, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::get_group_call_invite_link(GroupCallId group_call_id, bool can_self_unmute,
Promise<string> &&promise) { Promise<string> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::toggle_group_call_recording(GroupCallId group_call_id, bool is_enabled, string title,
bool record_video, bool use_portrait_orientation, bool record_video, bool use_portrait_orientation,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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, void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_call_id, int32 audio_source,
bool is_speaking, Promise<Unit> &&promise, int32 date) { bool is_speaking, Promise<Unit> &&promise, int32 date) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id)); 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); 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) { if (!is_recursive) {
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, audio_source, is_speaking, auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, audio_source, is_speaking,
promise = std::move(promise), date](Result<Unit> &&result) mutable { promise = std::move(promise), date](Result<Unit> &&result) mutable {
if (G()->close_flag()) {
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (result.is_error()) { if (result.is_error()) {
promise.set_value(Unit()); promise.set_value(Unit());
} else { } else {

View File

@ -1787,6 +1787,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
resolve_recent_inline_bots_multipromise_.add_promise(std::move(promise)); resolve_recent_inline_bots_multipromise_.add_promise(std::move(promise));
if (recently_used_bots_loaded_ == 0) { if (recently_used_bots_loaded_ == 0) {
resolve_recent_inline_bots_multipromise_.set_ignore_errors(true); 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) { if (!G()->parameters().use_chat_info_db) {
for (auto &bot_username : bot_usernames) { for (auto &bot_username : bot_usernames) {
td_->messages_manager_->search_public_dialog(bot_username, false, td_->messages_manager_->search_public_dialog(bot_username, false,
@ -1798,6 +1799,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
td_->contacts_manager_->get_user(user_id, 3, resolve_recent_inline_bots_multipromise_.get_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; recently_used_bots_loaded_ = 1;
} }
return false; return false;

View File

@ -1313,7 +1313,7 @@ void LanguagePackManager::save_strings_to_database(SqliteKeyValue *kv, int32 new
return; return;
} }
kv->begin_transaction().ensure(); kv->begin_write_transaction().ensure();
for (auto str : strings) { for (auto str : strings) {
if (!is_valid_key(str.first)) { if (!is_valid_key(str.first)) {
LOG(ERROR) << "Have invalid key \"" << str.first << '"'; LOG(ERROR) << "Have invalid key \"" << str.first << '"';
@ -1873,7 +1873,7 @@ void LanguagePackManager::send_with_promise(NetQueryPtr query, Promise<NetQueryP
void LanguagePackManager::hangup() { void LanguagePackManager::hangup() {
container_.for_each( container_.for_each(
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); [](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Global::request_aborted_error()); });
stop(); stop();
} }

View File

@ -3987,16 +3987,16 @@ unique_ptr<MessageContent> get_secret_message_content(
} }
auto url = r_http_url.ok().get_url(); 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<MessageText>(FormattedText{std::move(message_text), std::move(entities)}, WebPageId());
auto result = make_unique<MessageText>(FormattedText{std::move(message_text), std::move(entities)}, web_page_id); td->web_pages_manager_->get_web_page_by_url(
if (!result->web_page_id.is_valid()) { url,
load_data_multipromise.add_promise( PromiseCreator::lambda([&web_page_id = result->web_page_id, promise = load_data_multipromise.get_promise()](
PromiseCreator::lambda([td, url, &web_page_id = result->web_page_id](Result<Unit> result) { Result<WebPageId> r_web_page_id) mutable {
if (result.is_ok()) { if (r_web_page_id.is_ok()) {
web_page_id = td->web_pages_manager_->get_web_page_by_url(url); web_page_id = r_web_page_id.move_as_ok();
} }
})); promise.set_value(Unit());
} }));
return std::move(result); return std::move(result);
} }
case secret_api::decryptedMessageMediaExternalDocument::ID: { case secret_api::decryptedMessageMediaExternalDocument::ID: {

View File

@ -809,8 +809,8 @@ class MessagesDbImpl final : public MessagesDbSyncInterface {
return std::move(result); return std::move(result);
} }
Status begin_transaction() final { Status begin_write_transaction() final {
return db_.begin_transaction(); return db_.begin_write_transaction();
} }
Status commit_transaction() final { Status commit_transaction() final {
return db_.commit_transaction(); return db_.commit_transaction();
@ -1176,7 +1176,7 @@ class MessagesDbAsync final : public MessagesDbAsyncInterface {
if (pending_writes_.empty()) { if (pending_writes_.empty()) {
return; return;
} }
sync_db_->begin_transaction().ensure(); sync_db_->begin_write_transaction().ensure();
for (auto &query : pending_writes_) { for (auto &query : pending_writes_) {
query.set_value(Unit()); query.set_value(Unit());
} }

View File

@ -100,7 +100,7 @@ class MessagesDbSyncInterface {
virtual Result<MessagesDbCallsResult> get_calls(MessagesDbCallsQuery query) = 0; virtual Result<MessagesDbCallsResult> get_calls(MessagesDbCallsQuery query) = 0;
virtual Result<MessagesDbFtsResult> get_messages_fts(MessagesDbFtsQuery query) = 0; virtual Result<MessagesDbFtsResult> get_messages_fts(MessagesDbFtsQuery query) = 0;
virtual Status begin_transaction() = 0; virtual Status begin_write_transaction() = 0;
virtual Status commit_transaction() = 0; virtual Status commit_transaction() = 0;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -189,7 +189,7 @@ class MessagesManager final : public Actor {
int32 total_count = 0; int32 total_count = 0;
bool is_channel_messages = false; bool is_channel_messages = false;
}; };
MessagesInfo on_get_messages(tl_object_ptr<telegram_api::messages_Messages> &&messages_ptr, const char *source); MessagesInfo get_messages_info(tl_object_ptr<telegram_api::messages_Messages> &&messages_ptr, const char *source);
void get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info, void get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info,
Promise<MessagesInfo> &&promise); Promise<MessagesInfo> &&promise);
@ -197,7 +197,7 @@ class MessagesManager final : public Actor {
void get_channel_differences_if_needed(MessagesInfo &&messages_info, Promise<MessagesInfo> &&promise); void get_channel_differences_if_needed(MessagesInfo &&messages_info, Promise<MessagesInfo> &&promise);
void on_get_messages(vector<tl_object_ptr<telegram_api::Message>> &&messages, bool is_channel_message, void on_get_messages(vector<tl_object_ptr<telegram_api::Message>> &&messages, bool is_channel_message,
bool is_scheduled, const char *source); bool is_scheduled, Promise<Unit> &&promise, const char *source);
void on_get_history(DialogId dialog_id, MessageId from_message_id, MessageId old_last_new_message_id, int32 offset, 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<tl_object_ptr<telegram_api::Message>> &&messages, int32 limit, bool from_the_end, vector<tl_object_ptr<telegram_api::Message>> &&messages,
@ -211,7 +211,8 @@ class MessagesManager final : public Actor {
MessageId from_message_id, int32 offset, int32 limit, MessageId from_message_id, int32 offset, int32 limit,
MessageSearchFilter filter, MessageId top_thread_message_id, MessageSearchFilter filter, MessageId top_thread_message_id,
int64 random_id, int32 total_count, int64 random_id, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages); vector<tl_object_ptr<telegram_api::Message>> &&messages,
Promise<Unit> &&promise);
void on_failed_dialog_messages_search(DialogId dialog_id, int64 random_id); 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, 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, void on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id,
MessageId offset_message_id, int32 limit, MessageSearchFilter filter, MessageId offset_message_id, int32 limit, MessageSearchFilter filter,
int32 min_date, int32 max_date, int64 random_id, int32 total_count, int32 min_date, int32 max_date, int64 random_id, int32 total_count,
vector<tl_object_ptr<telegram_api::Message>> &&messages); vector<tl_object_ptr<telegram_api::Message>> &&messages, Promise<Unit> &&promise);
void on_failed_messages_search(int64 random_id); void on_failed_messages_search(int64 random_id);
void on_get_scheduled_server_messages(DialogId dialog_id, uint32 generation, 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, void block_message_sender_from_replies(MessageId message_id, bool delete_message, bool delete_all_messages,
bool report_spam, Promise<Unit> &&promise); bool report_spam, Promise<Unit> &&promise);
std::pair<int32, vector<DialogId>> get_blocked_dialogs(int32 offset, int32 limit, int64 &random_id, void get_blocked_dialogs(int32 offset, int32 limit, Promise<td_api::object_ptr<td_api::messageSenders>> &&promise);
Promise<Unit> &&promise);
void on_get_blocked_dialogs(int32 offset, int32 limit, int64 random_id, int32 total_count, void on_get_blocked_dialogs(int32 offset, int32 limit, int32 total_count,
vector<tl_object_ptr<telegram_api::peerBlocked>> &&blocked_peers); vector<tl_object_ptr<telegram_api::peerBlocked>> &&blocked_peers,
Promise<td_api::object_ptr<td_api::messageSenders>> &&promise);
void on_failed_get_blocked_dialogs(int64 random_id);
bool can_get_message_statistics(FullMessageId full_message_id); 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<Unit> &&promise); int64 get_dialog_message_by_date(DialogId dialog_id, int32 date, Promise<Unit> &&promise);
void on_get_dialog_message_by_date_success(DialogId dialog_id, int32 date, int64 random_id, void on_get_dialog_message_by_date_success(DialogId dialog_id, int32 date, int64 random_id,
vector<tl_object_ptr<telegram_api::Message>> &&messages); vector<tl_object_ptr<telegram_api::Message>> &&messages,
Promise<Unit> &&promise);
void on_get_dialog_message_by_date_fail(int64 random_id); 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<PendingSecretMessage> pending_secret_message, Promise<Unit> lock_promise = Auto()); void add_secret_message(unique_ptr<PendingSecretMessage> pending_secret_message, Promise<Unit> lock_promise = Auto());
void on_add_secret_message_ready(int64 token);
void finish_add_secret_message(unique_ptr<PendingSecretMessage> pending_secret_message); void finish_add_secret_message(unique_ptr<PendingSecretMessage> pending_secret_message);
void finish_delete_secret_messages(DialogId dialog_id, std::vector<int64> random_ids, Promise<> promise); void finish_delete_secret_messages(DialogId dialog_id, std::vector<int64> 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 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<Unit> &&result);
void load_folder_dialog_list_from_database(FolderId folder_id, int32 limit, Promise<Unit> &&promise); void load_folder_dialog_list_from_database(FolderId folder_id, int32 limit, Promise<Unit> &&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 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<td_api::updateChatFilters> get_update_chat_filters_object() const; td_api::object_ptr<td_api::updateChatFilters> get_update_chat_filters_object() const;
@ -3273,9 +3275,6 @@ class MessagesManager final : public Actor {
}; };
std::unordered_map<UserId, CommonDialogs, UserIdHash> found_common_dialogs_; std::unordered_map<UserId, CommonDialogs, UserIdHash> found_common_dialogs_;
std::unordered_map<int64, std::pair<int32, vector<DialogId>>>
found_blocked_dialogs_; // random_id -> [total_count, [dialog_id]...]
std::unordered_map<int64, FullMessageId> get_dialog_message_by_date_results_; std::unordered_map<int64, FullMessageId> get_dialog_message_by_date_results_;
std::unordered_map<int64, std::pair<int32, vector<MessageId>>> std::unordered_map<int64, std::pair<int32, vector<MessageId>>>

View File

@ -839,7 +839,7 @@ void PasswordManager::start_up() {
void PasswordManager::hangup() { void PasswordManager::hangup() {
container_.for_each( container_.for_each(
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); [](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Global::request_aborted_error()); });
stop(); stop();
} }

View File

@ -561,7 +561,7 @@ void PrivacyManager::send_with_promise(NetQueryPtr query, Promise<NetQueryPtr> p
void PrivacyManager::hangup() { void PrivacyManager::hangup() {
container_.for_each( container_.for_each(
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); [](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Global::request_aborted_error()); });
stop(); stop();
} }

View File

@ -129,6 +129,13 @@ void RecentDialogList::on_load_dialogs(vector<string> &&found_dialogs) {
auto promises = std::move(load_list_queries_); auto promises = std::move(load_list_queries_);
CHECK(!promises.empty()); 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_); auto newly_found_dialogs = std::move(dialog_ids_);
reset_to_empty(dialog_ids_); reset_to_empty(dialog_ids_);

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "td/telegram/AuthManager.h" #include "td/telegram/AuthManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
@ -127,7 +128,7 @@ class RequestActor : public Actor {
} }
void hangup() final { void hangup() final {
do_send_error(Status::Error(500, "Request aborted")); do_send_error(Global::request_aborted_error());
stop(); stop();
} }

View File

@ -1304,16 +1304,6 @@ Status SecretChatActor::do_inbound_message_decrypted(unique_ptr<log_event::Inbou
decrypted_message_service->random_id_, std::move(save_message_finish)); decrypted_message_service->random_id_, std::move(save_message_finish));
break; break;
default: 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()); save_message_finish.set_value(Unit());
break; break;
} }
@ -1379,7 +1369,7 @@ void SecretChatActor::on_save_changes_start(ChangesProcessor<StateChange>::Id sa
} }
void SecretChatActor::on_inbound_save_message_finish(uint64 state_id) { void SecretChatActor::on_inbound_save_message_finish(uint64 state_id) {
if (close_flag_) { if (close_flag_ || context_->close_flag()) {
return; return;
} }
auto *state = inbound_message_states_.get(state_id); auto *state = inbound_message_states_.get(state_id);

View File

@ -582,7 +582,7 @@ void SetSecureValue::loop() {
} }
void SetSecureValue::hangup() { void SetSecureValue::hangup() {
on_error(Status::Error(406, "Request aborted")); on_error(Status::Error(406, "Request canceled"));
} }
void SetSecureValue::tear_down() { void SetSecureValue::tear_down() {
@ -1294,7 +1294,7 @@ void SecureManager::get_preferred_country_language(string country_code,
void SecureManager::hangup() { void SecureManager::hangup() {
container_.for_each( container_.for_each(
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Status::Error(500, "Request aborted")); }); [](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Global::request_aborted_error()); });
dec_refcnt(); dec_refcnt();
} }

View File

@ -226,7 +226,7 @@ void SequenceDispatcher::tear_down() {
continue; continue;
} }
data.state_ = State::Dummy; data.state_ = State::Dummy;
data.query_->set_error(Status::Error(500, "Request aborted")); data.query_->set_error(Global::request_aborted_error());
do_finish(data); do_finish(data);
} }
} }

View File

@ -148,8 +148,25 @@ void SponsoredMessageManager::delete_cached_sponsored_messages(DialogId dialog_i
td_api::object_ptr<td_api::sponsoredMessage> SponsoredMessageManager::get_sponsored_message_object( td_api::object_ptr<td_api::sponsoredMessage> SponsoredMessageManager::get_sponsored_message_object(
DialogId dialog_id, const SponsoredMessage &sponsored_message) const { DialogId dialog_id, const SponsoredMessage &sponsored_message) const {
td_api::object_ptr<td_api::InternalLinkType> 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<td_api::internalLinkTypeBotStart>(bot_username, sponsored_message.start_param);
break;
}
default:
break;
}
return td_api::make_object<td_api::sponsoredMessage>( return td_api::make_object<td_api::sponsoredMessage>(
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)); 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()); CHECK(messages->message_random_ids.empty());
if (result.is_ok() && G()->close_flag()) { if (result.is_ok() && G()->close_flag()) {
result = Status::Error(500, "Request aborted"); result = Global::request_aborted_error();
} }
if (result.is_error()) { if (result.is_error()) {
dialog_sponsored_messages_.erase(dialog_id); dialog_sponsored_messages_.erase(dialog_id);

View File

@ -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()); auto set_id = search_sticker_set(set->short_name_, load_data_multipromise_ptr->get_promise());
if (!set_id.is_valid()) { if (!set_id.is_valid()) {
load_data_multipromise_ptr->add_promise( load_data_multipromise_ptr->add_promise(PromiseCreator::lambda(
PromiseCreator::lambda([td = td_, sticker_file_id, short_name = set->short_name_](Result<Unit> result) { [actor_id = actor_id(this), sticker_file_id, short_name = set->short_name_](Result<Unit> result) {
if (result.is_ok()) { if (result.is_ok()) {
// just in case // 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) { 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; LOG(INFO) << "Resolve sticker " << sticker_file_id << " set to " << short_name;
StickerSetId set_id = search_sticker_set(short_name, Auto()); StickerSetId set_id = search_sticker_set(short_name, Auto());
if (set_id.is_valid()) { 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, void StickersManager::do_reload_sticker_set(StickerSetId sticker_set_id,
tl_object_ptr<telegram_api::InputStickerSet> &&input_sticker_set, tl_object_ptr<telegram_api::InputStickerSet> &&input_sticker_set,
Promise<Unit> &&promise) const { Promise<Unit> &&promise) const {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
td_->create_handler<GetStickerSetQuery>(std::move(promise))->send(sticker_set_id, std::move(input_sticker_set)); td_->create_handler<GetStickerSetQuery>(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) { for (auto &emoji : new_dice_emojis) {
if (!td::contains(dice_emojis_, emoji)) { if (!td::contains(dice_emojis_, emoji)) {
auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_dice(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) { if (G()->parameters().use_file_db) {
LOG(INFO) << "Load new dice sticker set for emoji " << emoji; 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( void StickersManager::send_click_animated_emoji_message_response(
FileId sticker_id, Promise<td_api::object_ptr<td_api::sticker>> &&promise) { FileId sticker_id, Promise<td_api::object_ptr<td_api::sticker>> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
promise.set_value(get_sticker_object(sticker_id)); 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()); } 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); pending_new_sticker_sets_[random_id] = std::move(pending_new_sticker_set);
multipromise.add_promise(PromiseCreator::lambda([random_id](Result<Unit> result) { multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), random_id](Result<Unit> result) {
send_closure_later(G()->stickers_manager(), &StickersManager::on_new_stickers_uploaded, random_id, send_closure_later(actor_id, &StickersManager::on_new_stickers_uploaded, random_id, std::move(result));
std::move(result));
})); }));
auto lock_promise = multipromise.get_promise(); auto lock_promise = multipromise.get_promise();
@ -5448,6 +5453,9 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
pending_new_sticker_sets_.erase(it); pending_new_sticker_sets_.erase(it);
if (G()->close_flag()) {
result = Global::request_aborted_error();
}
if (result.is_error()) { if (result.is_error()) {
pending_new_sticker_set->promise.set_error(result.move_as_error()); pending_new_sticker_set->promise.set_error(result.move_as_error());
return; 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, void StickersManager::do_set_sticker_set_thumbnail(UserId user_id, string short_name,
tl_object_ptr<td_api::InputFile> &&thumbnail, tl_object_ptr<td_api::InputFile> &&thumbnail,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
auto it = short_name_to_sticker_set_id_.find(short_name); 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); 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<t
void StickersManager::send_save_recent_sticker_query(bool is_attached, FileId sticker_id, bool unsave, void StickersManager::send_save_recent_sticker_query(bool is_attached, FileId sticker_id, bool unsave,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
// TODO invokeAfter and log event // TODO invokeAfter and log event
auto file_view = td_->file_manager_->get_file_view(sticker_id); auto file_view = td_->file_manager_->get_file_view(sticker_id);
@ -6404,9 +6408,7 @@ void StickersManager::add_favorite_sticker(const tl_object_ptr<td_api::InputFile
} }
void StickersManager::send_fave_sticker_query(FileId sticker_id, bool unsave, Promise<Unit> &&promise) { void StickersManager::send_fave_sticker_query(FileId sticker_id, bool unsave, Promise<Unit> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
// TODO invokeAfter and log event // TODO invokeAfter and log event
auto file_view = td_->file_manager_->get_file_view(sticker_id); 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<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result) { const string &language_code, Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result) {
auto it = load_emoji_keywords_queries_.find(language_code); auto it = load_emoji_keywords_queries_.find(language_code);
CHECK(it != load_emoji_keywords_queries_.end()); CHECK(it != load_emoji_keywords_queries_.end());
CHECK(!it->second.empty());
auto promises = std::move(it->second); auto promises = std::move(it->second);
CHECK(!promises.empty());
load_emoji_keywords_queries_.erase(it); load_emoji_keywords_queries_.erase(it);
if (result.is_error()) { if (result.is_error()) {
@ -6919,8 +6921,7 @@ void StickersManager::on_get_emoji_keywords_difference(
} }
version = keywords->version_; version = keywords->version_;
auto *pmc = G()->td_db()->get_sqlite_sync_pmc(); auto *pmc = G()->td_db()->get_sqlite_sync_pmc();
pmc->begin_transaction().ensure(); pmc->begin_write_transaction().ensure();
// set must be the first operation to start a write transaction
pmc->set(get_emoji_language_code_version_database_key(language_code), to_string(version)); 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())); pmc->set(get_emoji_language_code_last_difference_time_database_key(language_code), to_string(G()->unix_time()));
for (auto &keyword_ptr : keywords->keywords_) { for (auto &keyword_ptr : keywords->keywords_) {

View File

@ -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<FileStats> promise) { void StorageManager::get_storage_stats(bool need_all_files, int32 dialog_limit, Promise<FileStats> promise) {
if (is_closed_) { if (is_closed_) {
promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Global::request_aborted_error());
return;
} }
if (pending_storage_stats_.size() != 0) { if (pending_storage_stats_.size() != 0) {
if (stats_dialog_limit_ == dialog_limit && need_all_files == stats_need_all_files_) { 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, void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_file_statistics,
Promise<FileStats> promise) { Promise<FileStats> promise) {
if (is_closed_) { 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()) { if (!pending_run_gc_[0].empty() || !pending_run_gc_[1].empty()) {
close_gc_worker(); close_gc_worker();
@ -126,7 +125,7 @@ void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_fil
std::move(file_stats)); 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)); 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<FileStats> r_file_stats) { void StorageManager::on_all_files(FileGcParameters gc_parameters, Result<FileStats> r_file_stats) {
int32 dialog_limit = gc_parameters.dialog_limit; int32 dialog_limit = gc_parameters.dialog_limit;
if (is_closed_ && r_file_stats.is_ok()) { 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()) { if (r_file_stats.is_error()) {
return on_gc_finished(dialog_limit, r_file_stats.move_as_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_); auto promises = std::move(pending_storage_stats_);
pending_storage_stats_.clear(); pending_storage_stats_.clear();
for (auto &promise : promises) { for (auto &promise : promises) {
promise.set_error(Status::Error(500, "Request aborted")); promise.set_error(Global::request_aborted_error());
} }
stats_generation_++; stats_generation_++;
stats_worker_.reset(); stats_worker_.reset();
@ -304,7 +303,7 @@ void StorageManager::close_gc_worker() {
pending_run_gc_[0].clear(); pending_run_gc_[0].clear();
pending_run_gc_[1].clear(); pending_run_gc_[1].clear();
for (auto &promise : promises) { for (auto &promise : promises) {
promise.set_error(Status::Error(500, "Request aborted")); promise.set_error(Global::request_aborted_error());
} }
gc_worker_.reset(); gc_worker_.reset();
gc_cancellation_token_source_.cancel(); gc_cancellation_token_source_.cancel();
@ -332,7 +331,7 @@ void StorageManager::schedule_next_gc() {
!G()->parameters().enable_storage_optimizer) { !G()->parameters().enable_storage_optimizer) {
next_gc_at_ = 0; next_gc_at_ = 0;
cancel_timeout(); cancel_timeout();
LOG(INFO) << "No next file gc is scheduled"; LOG(INFO) << "No next file clean up is scheduled";
return; return;
} }
auto sys_time = static_cast<uint32>(Clocks::system()); auto sys_time = static_cast<uint32>(Clocks::system());
@ -348,7 +347,7 @@ void StorageManager::schedule_next_gc() {
CHECK(next_gc_at >= sys_time); CHECK(next_gc_at >= sys_time);
auto next_gc_in = 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; next_gc_at_ = Time::now() + next_gc_in;
set_timeout_at(next_gc_at_); set_timeout_at(next_gc_at_);
} }
@ -364,7 +363,7 @@ void StorageManager::timeout_expired() {
next_gc_at_ = 0; next_gc_at_ = 0;
run_gc({}, false, PromiseCreator::lambda([actor_id = actor_id(this)](Result<FileStats> r_stats) { run_gc({}, false, PromiseCreator::lambda([actor_id = actor_id(this)](Result<FileStats> r_stats) {
if (!r_stats.is_error() || r_stats.error().code() != 500) { 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::save_last_gc_timestamp);
} }
send_closure(actor_id, &StorageManager::schedule_next_gc); send_closure(actor_id, &StorageManager::schedule_next_gc);

View File

@ -1596,15 +1596,22 @@ class GetWebPagePreviewRequest final : public RequestOnceActor {
} }
}; };
class GetWebPageInstantViewRequest final : public RequestActor<> { class GetWebPageInstantViewRequest final : public RequestActor<WebPageId> {
string url_; string url_;
bool force_full_; bool force_full_;
WebPageId web_page_id_; WebPageId web_page_id_;
void do_run(Promise<Unit> &&promise) final { void do_run(Promise<WebPageId> &&promise) final {
web_page_id_ = if (get_tries() < 2) {
td->web_pages_manager_->get_web_page_instant_view(url_, force_full_, get_tries() < 3, std::move(promise)); 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 { void do_send_result() final {
@ -1614,7 +1621,6 @@ class GetWebPageInstantViewRequest final : public RequestActor<> {
public: public:
GetWebPageInstantViewRequest(ActorShared<Td> td, uint64 request_id, string url, bool force_full) GetWebPageInstantViewRequest(ActorShared<Td> td, uint64 request_id, string url, bool force_full)
: RequestActor(std::move(td), request_id), url_(std::move(url)), force_full_(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<int32, vector<DialogId>> message_senders_;
void do_run(Promise<Unit> &&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<td_api::messageSenders>(message_senders_.first, std::move(senders)));
}
public:
GetBlockedMessageSendersRequest(ActorShared<Td> 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<> { class ImportContactsRequest final : public RequestActor<> {
vector<Contact> contacts_; vector<Contact> contacts_;
int64 random_id_; 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) { void Td::on_request(uint64 id, const td_api::getBlockedMessageSenders &request) {
CHECK_IS_USER(); 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) { void Td::on_request(uint64 id, td_api::addContact &request) {

View File

@ -277,6 +277,8 @@ void TdDb::do_close(Promise<> on_finished, bool destroy_flag) {
} }
binlog_.reset(); binlog_.reset();
} }
lock.set_value(Unit());
} }
Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters &parameters, DbKey key, DbKey old_key, Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters &parameters, DbKey key, DbKey old_key,

View File

@ -1656,7 +1656,9 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
} }
MultiPromiseActorSafe mpas{"OnPendingUpdatesMultiPromiseActor"}; MultiPromiseActorSafe mpas{"OnPendingUpdatesMultiPromiseActor"};
mpas.add_promise(std::move(promise)); mpas.add_promise([actor_id = actor_id(this), promise = std::move(promise)](Result<Unit> &&result) mutable {
send_closure(actor_id, &UpdatesManager::on_pending_updates_processed, std::move(result), std::move(promise));
});
auto lock = mpas.get_promise(); auto lock = mpas.get_promise();
for (auto &update : updates) { for (auto &update : updates) {
@ -1775,6 +1777,10 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
lock.set_value(Unit()); lock.set_value(Unit());
} }
void UpdatesManager::on_pending_updates_processed(Result<Unit> &&result, Promise<Unit> &&promise) {
promise.set_result(std::move(result));
}
void UpdatesManager::add_pending_qts_update(tl_object_ptr<telegram_api::Update> &&update, int32 qts, void UpdatesManager::add_pending_qts_update(tl_object_ptr<telegram_api::Update> &&update, int32 qts,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
CHECK(update != nullptr); CHECK(update != nullptr);

View File

@ -267,6 +267,8 @@ class UpdatesManager final : public Actor {
void on_pending_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, int32 seq_begin, int32 seq_end, void on_pending_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, int32 seq_begin, int32 seq_end,
int32 date, double receive_time, Promise<Unit> &&promise, const char *source); int32 date, double receive_time, Promise<Unit> &&promise, const char *source);
void on_pending_updates_processed(Result<Unit> &&result, Promise<Unit> &&promise);
void process_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, bool force_apply, void process_updates(vector<tl_object_ptr<telegram_api::Update>> &&updates, bool force_apply,
Promise<Unit> &&promise); Promise<Unit> &&promise);

View File

@ -94,12 +94,12 @@ class GetWebPagePreviewQuery final : public Td::ResultHandler {
}; };
class GetWebPageQuery final : public Td::ResultHandler { class GetWebPageQuery final : public Td::ResultHandler {
Promise<Unit> promise_; Promise<WebPageId> promise_;
WebPageId web_page_id_; WebPageId web_page_id_;
string url_; string url_;
public: public:
explicit GetWebPageQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) { explicit GetWebPageQuery(Promise<WebPageId> &&promise) : promise_(std::move(promise)) {
} }
void send(WebPageId web_page_id, const string &url, int32 hash) { 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_ ? web_page->cached_page_views_
: 0; : 0;
td->web_pages_manager_->on_get_web_page_instant_view_view_count(web_page_id_, view_count); 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 { } else {
LOG(ERROR) << "Receive webPageNotModified for " << url_; 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);
} }
auto web_page_id = td->web_pages_manager_->on_get_web_page(std::move(ptr), DialogId());
promise_.set_value(Unit()); 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 { void on_error(uint64 id, Status status) final {
@ -832,50 +832,44 @@ tl_object_ptr<td_api::webPage> WebPagesManager::get_web_page_preview_result(int6
return get_web_page_object(web_page_id); return get_web_page_object(web_page_id);
} }
WebPageId WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, bool force, void WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, Promise<WebPageId> &&promise) {
Promise<Unit> &&promise) {
LOG(INFO) << "Trying to get web page instant view for the url \"" << url << '"'; LOG(INFO) << "Trying to get web page instant view for the url \"" << url << '"';
auto it = url_to_web_page_id_.find(url); auto it = url_to_web_page_id_.find(url);
if (it != url_to_web_page_id_.end()) { if (it != url_to_web_page_id_.end()) {
if (it->second == WebPageId() && !force) { if (it->second == WebPageId()) {
// ignore negative caching // ignore negative caching
reload_web_page_by_url(url, std::move(promise)); return reload_web_page_by_url(url, std::move(promise));
return WebPageId();
} }
return get_web_page_instant_view(it->second, force_full, 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)); 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<Unit> &&promise) { void WebPagesManager::get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<WebPageId> &&promise) {
LOG(INFO) << "Trying to get web page instant view for " << web_page_id; 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); const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(web_page_id);
if (web_page_instant_view == nullptr) { if (web_page_instant_view == nullptr) {
promise.set_value(Unit()); return promise.set_value(WebPageId());
return WebPageId();
} }
if (!web_page_instant_view->is_loaded || (force_full && !web_page_instant_view->is_full)) { 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 load_web_page_instant_view(web_page_id, force_full, std::move(promise));
return WebPageId();
} }
if (force_full) { if (force_full) {
reload_web_page_instant_view(web_page_id); reload_web_page_instant_view(web_page_id);
} }
promise.set_value(Unit()); promise.set_value(std::move(web_page_id));
return web_page_id;
} }
string WebPagesManager::get_web_page_instant_view_database_key(WebPageId web_page_id) { string WebPagesManager::get_web_page_instant_view_database_key(WebPageId web_page_id) {
return PSTRING() << "wpiv" << web_page_id.get(); return PSTRING() << "wpiv" << web_page_id.get();
} }
void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<Unit> &&promise) { void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<WebPageId> &&promise) {
auto &load_web_page_instant_view_queries = load_web_page_instant_view_queries_[web_page_id]; auto &load_web_page_instant_view_queries = load_web_page_instant_view_queries_[web_page_id];
auto previous_queries = auto previous_queries =
load_web_page_instant_view_queries.partial.size() + load_web_page_instant_view_queries.full.size(); 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) { 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"; LOG(INFO) << "Trying to load " << web_page_id << " instant view from database";
G()->td_db()->get_sqlite_pmc()->get( G()->td_db()->get_sqlite_pmc()->get(
get_web_page_instant_view_database_key(web_page_id), PromiseCreator::lambda([web_page_id](string value) { get_web_page_instant_view_database_key(web_page_id),
send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_instant_view_from_database, PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](string value) {
web_page_id, std::move(value)); send_closure(actor_id, &WebPagesManager::on_load_web_page_instant_view_from_database, web_page_id,
std::move(value));
})); }));
} else { } else {
reload_web_page_instant_view(web_page_id); 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); const WebPage *web_page = get_web_page(web_page_id);
CHECK(web_page != nullptr && !web_page->instant_view.is_empty); CHECK(web_page != nullptr && !web_page->instant_view.is_empty);
auto promise = PromiseCreator::lambda([web_page_id](Result<> result) { auto promise = PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](Result<WebPageId> result) {
send_closure(G()->web_pages_manager(), &WebPagesManager::update_web_page_instant_view_load_requests, web_page_id, send_closure(actor_id, &WebPagesManager::update_web_page_instant_view_load_requests, web_page_id, true,
true, std::move(result)); std::move(result));
}); });
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
td_->create_handler<GetWebPageQuery>(std::move(promise)) td_->create_handler<GetWebPageQuery>(std::move(promise))
->send(web_page_id, web_page->url, web_page->instant_view.is_full ? web_page->instant_view.hash : 0); ->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); CHECK(G()->parameters().use_message_db);
LOG(INFO) << "Successfully loaded " << web_page_id << " instant view of size " << value.size() << " from database"; 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()); // 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); 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) { 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()) { if (!value.empty()) {
G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto()); 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; return;
} }
WebPage *web_page = web_page_it->second.get(); 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); 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, void WebPagesManager::update_web_page_instant_view_load_requests(WebPageId web_page_id, bool force_update,
Result<> result) { Result<WebPageId> r_web_page_id) {
if (G()->close_flag() && result.is_error()) { if (G()->close_flag()) {
result = Status::Error(500, "Request aborted"); r_web_page_id = Global::request_aborted_error();
} }
LOG(INFO) << "Update load requests for " << web_page_id; LOG(INFO) << "Update load requests for " << web_page_id;
auto it = load_web_page_instant_view_queries_.find(web_page_id); auto it = load_web_page_instant_view_queries_.find(web_page_id);
if (it == load_web_page_instant_view_queries_.end()) { if (it == load_web_page_instant_view_queries_.end()) {
return; return;
} }
vector<Promise<Unit>> promises[2]; vector<Promise<WebPageId>> promises[2];
promises[0] = std::move(it->second.partial); promises[0] = std::move(it->second.partial);
promises[1] = std::move(it->second.full); promises[1] = std::move(it->second.full);
reset_to_empty(it->second.partial); reset_to_empty(it->second.partial);
reset_to_empty(it->second.full); reset_to_empty(it->second.full);
load_web_page_instant_view_queries_.erase(it); load_web_page_instant_view_queries_.erase(it);
if (result.is_error()) { if (r_web_page_id.is_error()) {
LOG(INFO) << "Receive error " << result.error() << " for load " << web_page_id; LOG(INFO) << "Receive error " << r_web_page_id.error() << " for load " << web_page_id;
combine(promises[0], std::move(promises[1])); combine(promises[0], std::move(promises[1]));
for (auto &promise : promises[0]) { for (auto &promise : promises[0]) {
promise.set_error(result.error().clone()); promise.set_error(r_web_page_id.error().clone());
} }
return; 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) { if (web_page_instant_view == nullptr) {
combine(promises[0], std::move(promises[1])); combine(promises[0], std::move(promises[1]));
for (auto &promise : promises[0]) { for (auto &promise : promises[0]) {
promise.set_value(Unit()); promise.set_value(WebPageId());
} }
return; return;
} }
@ -1010,26 +1004,27 @@ void WebPagesManager::update_web_page_instant_view_load_requests(WebPageId web_p
} }
for (auto &promise : promises[0]) { for (auto &promise : promises[0]) {
promise.set_value(Unit()); promise.set_value(WebPageId(new_web_page_id));
} }
reset_to_empty(promises[0]); reset_to_empty(promises[0]);
} }
if (!promises[0].empty() || !promises[1].empty()) { if (!promises[0].empty() || !promises[1].empty()) {
if (force_update) { if (force_update) {
// protection from cycles // 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])); combine(promises[0], std::move(promises[1]));
for (auto &promise : promises[0]) { for (auto &promise : promises[0]) {
promise.set_value(Unit()); promise.set_value(WebPageId());
} }
return; 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(); auto old_size = load_queries.partial.size() + load_queries.full.size();
combine(load_queries.partial, std::move(promises[0])); combine(load_queries.partial, std::move(promises[0]));
combine(load_queries.full, std::move(promises[1])); combine(load_queries.full, std::move(promises[1]));
if (old_size == 0) { 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(); return WebPageId();
} }
WebPageId WebPagesManager::get_web_page_by_url(const string &url, Promise<Unit> &&promise) { void WebPagesManager::get_web_page_by_url(const string &url, Promise<WebPageId> &&promise) {
LOG(INFO) << "Trying to get web page identifier for the url \"" << url << '"'; LOG(INFO) << "Trying to get web page identifier for the url \"" << url << '"';
auto it = url_to_web_page_id_.find(url); auto it = url_to_web_page_id_.find(url);
if (it != url_to_web_page_id_.end()) { if (it != url_to_web_page_id_.end()) {
promise.set_value(Unit()); return promise.set_value(WebPageId(it->second));
return it->second;
} }
load_web_page_by_url(url, std::move(promise)); load_web_page_by_url(url, std::move(promise));
return WebPageId();
} }
void WebPagesManager::load_web_page_by_url(const string &url, Promise<Unit> &&promise) { void WebPagesManager::load_web_page_by_url(const string &url, Promise<WebPageId> &&promise) {
if (!G()->parameters().use_message_db) { if (!G()->parameters().use_message_db) {
reload_web_page_by_url(url, std::move(promise)); return reload_web_page_by_url(url, std::move(promise));
return;
} }
LOG(INFO) << "Load \"" << url << '"'; LOG(INFO) << "Load \"" << url << '"';
G()->td_db()->get_sqlite_pmc()->get(get_web_page_url_database_key(url), G()->td_db()->get_sqlite_pmc()->get(
PromiseCreator::lambda([url, promise = std::move(promise)](string value) mutable { get_web_page_url_database_key(url),
send_closure(G()->web_pages_manager(), PromiseCreator::lambda([actor_id = actor_id(this), url, promise = std::move(promise)](string value) mutable {
&WebPagesManager::on_load_web_page_id_by_url_from_database, url, send_closure(actor_id, &WebPagesManager::on_load_web_page_id_by_url_from_database, std::move(url),
value, std::move(promise)); std::move(value), std::move(promise));
})); }));
} }
void WebPagesManager::on_load_web_page_id_by_url_from_database(const string &url, string value, void WebPagesManager::on_load_web_page_id_by_url_from_database(string url, string value, Promise<WebPageId> &&promise) {
Promise<Unit> &&promise) { TRY_STATUS_PROMISE(promise, G()->close_status());
if (G()->close_flag()) {
return;
}
LOG(INFO) << "Successfully loaded url \"" << url << "\" of size " << value.size() << " from database"; 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()); // 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); auto it = url_to_web_page_id_.find(url);
if (it != url_to_web_page_id_.end()) { if (it != url_to_web_page_id_.end()) {
// URL web page has already been loaded // URL web page has already been loaded
promise.set_value(Unit()); return promise.set_value(WebPageId(it->second));
return;
} }
if (!value.empty()) { if (!value.empty()) {
auto web_page_id = WebPageId(to_integer<int64>(value)); auto web_page_id = WebPageId(to_integer<int64>(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)) { if (have_web_page(web_page_id)) {
// URL web page has already been loaded // URL web page has already been loaded
on_get_web_page_by_url(url, web_page_id, true); on_get_web_page_by_url(url, web_page_id, true);
promise.set_value(Unit()); promise.set_value(WebPageId(web_page_id));
return; return;
} }
load_web_page_from_database( load_web_page_from_database(web_page_id,
web_page_id, PromiseCreator::lambda([actor_id = actor_id(this), web_page_id, url = std::move(url),
PromiseCreator::lambda([web_page_id, url, promise = std::move(promise)](Result<> result) mutable { promise = std::move(promise)](Result<Unit> result) mutable {
send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_by_url_from_database, web_page_id, send_closure(actor_id, &WebPagesManager::on_load_web_page_by_url_from_database,
url, std::move(promise), std::move(result)); web_page_id, std::move(url), std::move(promise), std::move(result));
})); }));
return; return;
} else { } else {
LOG(ERROR) << "Receive invalid " << web_page_id; 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)); 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, void WebPagesManager::on_load_web_page_by_url_from_database(WebPageId web_page_id, string url,
Promise<Unit> &&promise, Result<> result) { Promise<WebPageId> &&promise, Result<Unit> &&result) {
if (result.is_error()) { if (result.is_error()) {
CHECK(G()->close_flag()); CHECK(G()->close_flag());
promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Global::request_aborted_error());
return;
} }
const WebPage *web_page = get_web_page(web_page_id); const WebPage *web_page = get_web_page(web_page_id);
if (web_page == nullptr) { if (web_page == nullptr) {
reload_web_page_by_url(url, std::move(promise)); return reload_web_page_by_url(url, std::move(promise));
return;
} }
if (web_page->url != url) { if (web_page->url != url) {
on_get_web_page_by_url(url, web_page_id, true); 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<Unit> &&promise) { void WebPagesManager::reload_web_page_by_url(const string &url, Promise<WebPageId> &&promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
LOG(INFO) << "Reload url \"" << url << '"';
td_->create_handler<GetWebPageQuery>(std::move(promise))->send(WebPageId(), url, 0); td_->create_handler<GetWebPageQuery>(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"; LOG(INFO) << "Save " << web_page_id << " to database";
G()->td_db()->get_sqlite_pmc()->set( G()->td_db()->get_sqlite_pmc()->set(
get_web_page_database_key(web_page_id), log_event_store(*web_page).as_slice().str(), get_web_page_database_key(web_page_id), log_event_store(*web_page).as_slice().str(),
PromiseCreator::lambda([web_page_id](Result<> result) { PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](Result<> result) {
send_closure(G()->web_pages_manager(), &WebPagesManager::on_save_web_page_to_database, web_page_id, send_closure(actor_id, &WebPagesManager::on_save_web_page_to_database, web_page_id, result.is_ok());
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]; auto &load_web_page_queries = load_web_page_from_database_queries_[web_page_id];
load_web_page_queries.push_back(std::move(promise)); load_web_page_queries.push_back(std::move(promise));
if (load_web_page_queries.size() == 1u) { if (load_web_page_queries.size() == 1u) {
G()->td_db()->get_sqlite_pmc()->get( G()->td_db()->get_sqlite_pmc()->get(get_web_page_database_key(web_page_id),
get_web_page_database_key(web_page_id), PromiseCreator::lambda([web_page_id](string value) { PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](string value) {
send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_from_database, web_page_id, send_closure(actor_id, &WebPagesManager::on_load_web_page_from_database,
std::move(value)); 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"; 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()); // 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 (!have_web_page(web_page_id)) {
if (!value.empty()) { if (!value.empty()) {

View File

@ -67,13 +67,13 @@ class WebPagesManager final : public Actor {
tl_object_ptr<td_api::webPage> get_web_page_preview_result(int64 request_id); tl_object_ptr<td_api::webPage> get_web_page_preview_result(int64 request_id);
WebPageId get_web_page_instant_view(const string &url, bool force_full, bool force, Promise<Unit> &&promise); void get_web_page_instant_view(const string &url, bool force_full, Promise<WebPageId> &&promise);
WebPageId get_web_page_by_url(const string &url) const; WebPageId get_web_page_by_url(const string &url) const;
WebPageId get_web_page_by_url(const string &url, Promise<Unit> &&promise); void get_web_page_by_url(const string &url, Promise<WebPageId> &&promise);
void reload_web_page_by_url(const string &url, Promise<Unit> &&promise); void reload_web_page_by_url(const string &url, Promise<WebPageId> &&promise);
void on_get_web_page_preview_success(int64 request_id, const string &url, void on_get_web_page_preview_success(int64 request_id, const string &url,
tl_object_ptr<telegram_api::MessageMedia> &&message_media_ptr, tl_object_ptr<telegram_api::MessageMedia> &&message_media_ptr,
@ -125,7 +125,7 @@ class WebPagesManager final : public Actor {
const WebPageInstantView *get_web_page_instant_view(WebPageId web_page_id) const; 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<Unit> &&promise); void get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<WebPageId> &&promise);
tl_object_ptr<td_api::webPageInstantView> get_web_page_instant_view_object( tl_object_ptr<td_api::webPageInstantView> get_web_page_instant_view_object(
WebPageId web_page_id, const WebPageInstantView *web_page_instant_view) const; 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); 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<Unit> &&promise); void load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<WebPageId> &&promise);
void on_load_web_page_instant_view_from_database(WebPageId web_page_id, string value); 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 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<WebPageId> r_web_page_id);
static string get_web_page_url_database_key(const string &url); static string get_web_page_url_database_key(const string &url);
void load_web_page_by_url(const string &url, Promise<Unit> &&promise); void load_web_page_by_url(const string &url, Promise<WebPageId> &&promise);
void on_load_web_page_id_by_url_from_database(const string &url, string value, Promise<Unit> &&promise); void on_load_web_page_id_by_url_from_database(string url, string value, Promise<WebPageId> &&promise);
void on_load_web_page_by_url_from_database(WebPageId web_page_id, const string &url, Promise<Unit> &&promise, void on_load_web_page_by_url_from_database(WebPageId web_page_id, string url, Promise<WebPageId> &&promise,
Result<> result); Result<Unit> &&result);
void tear_down() final; void tear_down() final;
@ -186,8 +187,8 @@ class WebPagesManager final : public Actor {
std::unordered_set<WebPageId, WebPageIdHash> loaded_from_database_web_pages_; std::unordered_set<WebPageId, WebPageIdHash> loaded_from_database_web_pages_;
struct PendingWebPageInstantViewQueries { struct PendingWebPageInstantViewQueries {
vector<Promise<Unit>> partial; vector<Promise<WebPageId>> partial;
vector<Promise<Unit>> full; vector<Promise<WebPageId>> full;
}; };
std::unordered_map<WebPageId, PendingWebPageInstantViewQueries, WebPageIdHash> load_web_page_instant_view_queries_; std::unordered_map<WebPageId, PendingWebPageInstantViewQueries, WebPageIdHash> load_web_page_instant_view_queries_;

View File

@ -23,7 +23,6 @@
#include "td/utils/format.h" #include "td/utils/format.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/misc.h" #include "td/utils/misc.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/SliceBuilder.h" #include "td/utils/SliceBuilder.h"
#include "td/utils/Status.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) { void clear_file_data(FileDbId id, const string &remote_key, const string &local_key, const string &generate_key) {
auto &pmc = file_pmc(); auto &pmc = file_pmc();
pmc.begin_transaction().ensure(); pmc.begin_write_transaction().ensure();
SCOPE_EXIT {
pmc.commit_transaction().ensure();
};
if (id > current_pmc_id_) { if (id > current_pmc_id_) {
pmc.set("file_id", to_string(id.get())); pmc.set("file_id", to_string(id.get()));
@ -89,27 +85,26 @@ class FileDb final : public FileDbInterface {
} }
pmc.erase(PSTRING() << "file" << id.get()); 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()) { if (!remote_key.empty()) {
pmc.erase(remote_key); 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()) { if (!local_key.empty()) {
pmc.erase(local_key); 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()) { if (!generate_key.empty()) {
pmc.erase(generate_key); 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, void store_file_data(FileDbId id, const string &file_data, const string &remote_key, const string &local_key,
const string &generate_key) { const string &generate_key) {
auto &pmc = file_pmc(); auto &pmc = file_pmc();
pmc.begin_transaction().ensure(); pmc.begin_write_transaction().ensure();
SCOPE_EXIT {
pmc.commit_transaction().ensure();
};
if (id > current_pmc_id_) { if (id > current_pmc_id_) {
pmc.set("file_id", to_string(id.get())); pmc.set("file_id", to_string(id.get()));
@ -127,13 +122,12 @@ class FileDb final : public FileDbInterface {
if (!generate_key.empty()) { if (!generate_key.empty()) {
pmc.set(generate_key, to_string(id.get())); pmc.set(generate_key, to_string(id.get()));
} }
pmc.commit_transaction().ensure();
} }
void store_file_data_ref(FileDbId id, FileDbId new_id) { void store_file_data_ref(FileDbId id, FileDbId new_id) {
auto &pmc = file_pmc(); auto &pmc = file_pmc();
pmc.begin_transaction().ensure(); pmc.begin_write_transaction().ensure();
SCOPE_EXIT {
pmc.commit_transaction().ensure();
};
if (id > current_pmc_id_) { if (id > current_pmc_id_) {
pmc.set("file_id", to_string(id.get())); 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); do_store_file_data_ref(id, new_id);
pmc.commit_transaction().ensure();
} }
void optimize_refs(const std::vector<FileDbId> ids, FileDbId main_id) { void optimize_refs(const std::vector<FileDbId> ids, FileDbId main_id) {
LOG(INFO) << "Optimize " << ids.size() << " ids in file database to " << main_id.get(); LOG(INFO) << "Optimize " << ids.size() << " ids in file database to " << main_id.get();
auto &pmc = file_pmc(); auto &pmc = file_pmc();
pmc.begin_transaction().ensure(); pmc.begin_write_transaction().ensure();
SCOPE_EXIT {
pmc.commit_transaction().ensure();
};
for (size_t i = 0; i + 1 < ids.size(); i++) { for (size_t i = 0; i + 1 < ids.size(); i++) {
do_store_file_data_ref(ids[i], main_id); do_store_file_data_ref(ids[i], main_id);
} }
pmc.commit_transaction().ensure();
} }
private: private:
@ -221,10 +215,10 @@ class FileDb final : public FileDbInterface {
if (file_data.generate_ != nullptr && new_generate) { if (file_data.generate_ != nullptr && new_generate) {
generate_key = as_key(*file_data.generate_); generate_key = as_key(*file_data.generate_);
} }
LOG(DEBUG) << "SAVE " << id.get() << " -> " << file_data << " " // LOG(DEBUG) << "SAVE " << id.get() << " -> " << file_data << " "
<< tag("remote_key", format::as_hex_dump<4>(Slice(remote_key))) // << tag("remote_key", format::as_hex_dump<4>(Slice(remote_key)))
<< tag("local_key", format::as_hex_dump<4>(Slice(local_key))) // << tag("local_key", format::as_hex_dump<4>(Slice(local_key)))
<< tag("generate_key", format::as_hex_dump<4>(Slice(generate_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, send_closure(file_db_actor_, &FileDbActor::store_file_data, id, serialize(file_data), remote_key, local_key,
generate_key); generate_key);
} }
@ -243,7 +237,7 @@ class FileDb final : public FileDbInterface {
static Result<FileData> load_file_data_impl(ActorId<FileDbActor> file_db_actor_id, SqliteKeyValue &pmc, static Result<FileData> load_file_data_impl(ActorId<FileDbActor> file_db_actor_id, SqliteKeyValue &pmc,
const string &key, FileDbId current_pmc_id) { 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)); TRY_RESULT(id, get_id(pmc, key));
vector<FileDbId> ids; vector<FileDbId> ids;
@ -270,8 +264,8 @@ class FileDb final : public FileDbInterface {
if (ids.size() > 1) { if (ids.size() > 1) {
send_closure(file_db_actor_id, &FileDbActor::optimize_refs, std::move(ids), id); 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(DEBUG) << "By ID " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str));
//LOG(INFO) << attempt_count; // LOG(INFO) << attempt_count;
log_event::WithVersion<TlParser> parser(data_str); log_event::WithVersion<TlParser> parser(data_str);
parser.set_version(static_cast<int32>(Version::Initial)); parser.set_version(static_cast<int32>(Version::Initial));
@ -287,7 +281,7 @@ class FileDb final : public FileDbInterface {
static Result<FileDbId> get_id(SqliteKeyValue &pmc, const string &key) TD_WARN_UNUSED_RESULT { static Result<FileDbId> get_id(SqliteKeyValue &pmc, const string &key) TD_WARN_UNUSED_RESULT {
auto id_str = pmc.get(key); 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()) { if (id_str.empty()) {
return Status::Error("There is no such a key in database"); return Status::Error("There is no such a key in database");
} }

View File

@ -132,7 +132,7 @@ void FileGcWorker::run_gc(const FileGcParameters &parameters, std::vector<FullFi
return false; return false;
}); });
if (token_) { if (token_) {
return promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Global::request_aborted_error());
} }
// sort by max(atime, mtime) // sort by max(atime, mtime)
@ -152,7 +152,7 @@ void FileGcWorker::run_gc(const FileGcParameters &parameters, std::vector<FullFi
size_t pos = 0; size_t pos = 0;
while (pos < files.size() && (remove_count > 0 || remove_size > 0)) { while (pos < files.size() && (remove_count > 0 || remove_size > 0)) {
if (token_) { if (token_) {
return promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Global::request_aborted_error());
} }
if (remove_count > 0) { if (remove_count > 0) {
remove_by_count_cnt++; remove_by_count_cnt++;

View File

@ -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<Unit> &&result, void FileManager::on_file_reference_repaired(FileId file_id, FileSourceId file_source_id, Result<Unit> &&result,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
auto file_view = get_file_view(file_id); auto file_view = get_file_view(file_id);
CHECK(!file_view.empty()); CHECK(!file_view.empty());
if (result.is_ok() && if (result.is_ok() &&
@ -2030,9 +2032,7 @@ void FileManager::get_content(FileId file_id, Promise<BufferSlice> promise) {
void FileManager::read_file_part(FileId file_id, int32 offset, int32 count, int left_tries, void FileManager::read_file_part(FileId file_id, int32 offset, int32 count, int left_tries,
Promise<td_api::object_ptr<td_api::filePart>> promise) { Promise<td_api::object_ptr<td_api::filePart>> promise) {
if (G()->close_flag()) { TRY_STATUS_PROMISE(promise, G()->close_status());
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (!file_id.is_valid()) { if (!file_id.is_valid()) {
return promise.set_error(Status::Error(400, "File identifier is invalid")); 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) { if (priority == 0) {
node->set_download_priority(priority); node->set_download_priority(priority);
LOG(INFO) << "Cancel downloading of file " << node->main_file_id_;
if (old_priority != 0) { if (old_priority != 0) {
LOG(INFO) << "Cancel downloading of file " << node->main_file_id_;
do_cancel_download(node); do_cancel_download(node);
} }
return; return;
@ -2640,7 +2640,7 @@ void FileManager::run_generate(FileNodePtr node) {
} }
FileView file_view(node); FileView file_view(node);
if (!file_view.can_generate()) { 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; return;
} }
if (file_view.has_local_location()) { if (file_view.has_local_location()) {
@ -2732,8 +2732,6 @@ void FileManager::run_upload(FileNodePtr node, std::vector<int> bad_parts) {
if (old_priority != 0) { if (old_priority != 0) {
LOG(INFO) << "Cancel file " << file_id << " uploading"; LOG(INFO) << "Cancel file " << file_id << " uploading";
do_cancel_upload(node); do_cancel_upload(node);
} else {
LOG(INFO) << "File " << file_id << " upload priority is still 0";
} }
return; return;
} }
@ -3872,7 +3870,7 @@ void FileManager::hangup() {
while (!queries_container_.empty()) { while (!queries_container_.empty()) {
auto ids = queries_container_.ids(); auto ids = queries_container_.ids();
for (auto id : ids) { for (auto id : ids) {
on_error(id, Status::Error(500, "Request aborted")); on_error(id, Global::request_aborted_error());
} }
} }
is_closed_ = true; is_closed_ = true;

View File

@ -161,7 +161,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
auto passed = Time::now() - start; auto passed = Time::now() - start;
LOG_IF(INFO, passed > 0.5) << "Get file stats took: " << format::as_time(passed); LOG_IF(INFO, passed > 0.5) << "Get file stats took: " << format::as_time(passed);
if (token_) { 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)); promise.set_value(std::move(file_stats));
} else { } else {
@ -182,7 +182,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
}); });
if (token_) { if (token_) {
return promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Global::request_aborted_error());
} }
std::unordered_map<size_t, size_t> hash_to_pos; std::unordered_map<size_t, size_t> 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<std::string>()(full_info.path)] = pos; hash_to_pos[std::hash<std::string>()(full_info.path)] = pos;
pos++; pos++;
if (token_) { 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) { 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; full_infos[it->second].owner_dialog_id = db_info.owner_dialog_id;
}); });
if (token_) { 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); FileStats file_stats(need_all_files, split_by_owner_dialog_id);
for (auto &full_info : full_infos) { for (auto &full_info : full_infos) {
file_stats.add(std::move(full_info)); file_stats.add(std::move(full_info));
if (token_) { if (token_) {
return promise.set_error(Status::Error(500, "Request aborted")); return promise.set_error(Global::request_aborted_error());
} }
} }
auto passed = Time::now() - start; auto passed = Time::now() - start;

View File

@ -6,6 +6,7 @@
// //
#pragma once #pragma once
#include "td/telegram/Global.h"
#include "td/telegram/net/NetQuery.h" #include "td/telegram/net/NetQuery.h"
#include "td/actor/actor.h" #include "td/actor/actor.h"
@ -40,7 +41,7 @@ class NetActor : public NetQueryCallback {
class NetActorOnce : public NetActor { class NetActorOnce : public NetActor {
void hangup() override { void hangup() override {
on_error(0, Status::Error(500, "Request aborted")); on_error(0, Global::request_aborted_error());
stop(); stop();
} }

View File

@ -116,7 +116,7 @@ void NetQueryDelayer::on_slot_event(uint64 id) {
void NetQueryDelayer::tear_down() { void NetQueryDelayer::tear_down() {
container_.for_each([](auto id, auto &query_slot) { 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_)); G()->net_query_dispatcher().dispatch(std::move(query_slot.query_));
}); });
} }

View File

@ -6,6 +6,8 @@
// //
#include "td/telegram/net/NetQueryDispatcher.h" #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/AuthDataShared.h"
#include "td/telegram/net/DcAuthManager.h" #include "td/telegram/net/DcAuthManager.h"
#include "td/telegram/net/NetQuery.h" #include "td/telegram/net/NetQuery.h"
@ -13,9 +15,6 @@
#include "td/telegram/net/PublicRsaKeyShared.h" #include "td/telegram/net/PublicRsaKeyShared.h"
#include "td/telegram/net/PublicRsaKeyWatchdog.h" #include "td/telegram/net/PublicRsaKeyWatchdog.h"
#include "td/telegram/net/SessionMultiProxy.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/Td.h"
#include "td/telegram/TdDb.h" #include "td/telegram/TdDb.h"
#include "td/telegram/telegram_api.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) { void NetQueryDispatcher::dispatch(NetQueryPtr net_query) {
// net_query->debug("dispatch"); // net_query->debug("dispatch");
if (stop_flag_.load(std::memory_order_relaxed)) { 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)); return complete_net_query(std::move(net_query));
} }
if (G()->shared_config().get_option_boolean("test_flood_wait")) { if (G()->shared_config().get_option_boolean("test_flood_wait")) {

View File

@ -75,6 +75,7 @@ class Actor : public ObserverBase {
void do_migrate(int32 sched_id); void do_migrate(int32 sched_id);
uint64 get_link_token(); uint64 get_link_token();
std::weak_ptr<ActorContext> get_context_weak_ptr() const;
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context); std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
string set_tag(string tag); string set_tag(string tag);

View File

@ -79,18 +79,26 @@ std::enable_if_t<std::is_base_of<Actor, ActorType>::value> start_migrate(ActorTy
Scheduler::instance()->start_migrate_actor(&obj, sched_id); Scheduler::instance()->start_migrate_actor(&obj, sched_id);
} }
} }
template <class ActorType> template <class ActorType>
std::enable_if_t<std::is_base_of<Actor, ActorType>::value> finish_migrate(ActorType &obj) { std::enable_if_t<std::is_base_of<Actor, ActorType>::value> finish_migrate(ActorType &obj) {
if (!obj.empty()) { if (!obj.empty()) {
Scheduler::instance()->finish_migrate_actor(&obj); Scheduler::instance()->finish_migrate_actor(&obj);
} }
} }
inline uint64 Actor::get_link_token() { inline uint64 Actor::get_link_token() {
return Scheduler::instance()->get_link_token(this); return Scheduler::instance()->get_link_token(this);
} }
inline std::weak_ptr<ActorContext> Actor::get_context_weak_ptr() const {
return info_->get_context_weak_ptr();
}
inline std::shared_ptr<ActorContext> Actor::set_context(std::shared_ptr<ActorContext> context) { inline std::shared_ptr<ActorContext> Actor::set_context(std::shared_ptr<ActorContext> context) {
return info_->set_context(std::move(context)); return info_->set_context(std::move(context));
} }
inline string Actor::set_tag(string tag) { inline string Actor::set_tag(string tag) {
auto *ctx = info_->get_context(); auto *ctx = info_->get_context();
string old_tag; string old_tag;
@ -105,12 +113,14 @@ inline string Actor::set_tag(string tag) {
inline void Actor::init(ObjectPool<ActorInfo>::OwnerPtr &&info) { inline void Actor::init(ObjectPool<ActorInfo>::OwnerPtr &&info) {
info_ = std::move(info); info_ = std::move(info);
} }
inline ActorInfo *Actor::get_info() { inline ActorInfo *Actor::get_info() {
return &*info_; return &*info_;
} }
inline const ActorInfo *Actor::get_info() const { inline const ActorInfo *Actor::get_info() const {
return &*info_; return &*info_;
} }
inline ObjectPool<ActorInfo>::OwnerPtr Actor::clear() { inline ObjectPool<ActorInfo>::OwnerPtr Actor::clear() {
return std::move(info_); return std::move(info_);
} }

View File

@ -86,6 +86,7 @@ class ActorInfo final
const Actor *get_actor_unsafe() const; const Actor *get_actor_unsafe() const;
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context); std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
std::weak_ptr<ActorContext> get_context_weak_ptr() const;
ActorContext *get_context(); ActorContext *get_context();
const ActorContext *get_context() const; const ActorContext *get_context() const;
CSlice get_name() const; CSlice get_name() const;

View File

@ -156,6 +156,11 @@ inline std::shared_ptr<ActorContext> ActorInfo::set_context(std::shared_ptr<Acto
Scheduler::on_context_updated(); Scheduler::on_context_updated();
return context; return context;
} }
inline std::weak_ptr<ActorContext> ActorInfo::get_context_weak_ptr() const {
return context_;
}
inline const ActorContext *ActorInfo::get_context() const { inline const ActorContext *ActorInfo::get_context() const {
return context_.get(); return context_.get();
} }

View File

@ -13,31 +13,29 @@
#include "td/utils/Random.h" #include "td/utils/Random.h"
#include "td/utils/tests.h" #include "td/utils/tests.h"
using namespace td;
TEST(MultiTimeout, bug) { TEST(MultiTimeout, bug) {
ConcurrentScheduler sched; td::ConcurrentScheduler sched;
int threads_n = 0; int threads_n = 0;
sched.init(threads_n); sched.init(threads_n);
sched.start(); sched.start();
unique_ptr<MultiTimeout> multi_timeout; td::unique_ptr<td::MultiTimeout> multi_timeout;
struct Data { struct Data {
MultiTimeout *multi_timeout; td::MultiTimeout *multi_timeout;
}; };
Data data; Data data;
{ {
auto guard = sched.get_main_guard(); auto guard = sched.get_main_guard();
multi_timeout = make_unique<MultiTimeout>("MultiTimeout"); multi_timeout = td::make_unique<td::MultiTimeout>("MultiTimeout");
data.multi_timeout = multi_timeout.get(); 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<Data *>(void_data); auto &data = *static_cast<Data *>(void_data);
if (key == 1) { if (key == 1) {
data.multi_timeout->cancel_timeout(key + 1); data.multi_timeout->cancel_timeout(key + 1);
data.multi_timeout->set_timeout_in(key + 2, 1); data.multi_timeout->set_timeout_in(key + 2, 1);
} else { } else {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
}); });
multi_timeout->set_callback_data(&data); multi_timeout->set_callback_data(&data);
@ -51,9 +49,9 @@ TEST(MultiTimeout, bug) {
sched.finish(); sched.finish();
} }
class TimeoutManager final : public Actor { class TimeoutManager final : public td::Actor {
public: public:
static int32 count; static td::int32 count;
TimeoutManager() { TimeoutManager() {
count++; count++;
@ -70,7 +68,7 @@ class TimeoutManager final : public Actor {
LOG(INFO) << "Destroy TimeoutManager"; 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); CHECK(count >= 0);
if (count == 0) { if (count == 0) {
LOG(ERROR) << "Receive timeout after manager was closed"; LOG(ERROR) << "Receive timeout after manager was closed";
@ -84,21 +82,21 @@ class TimeoutManager final : public Actor {
void test_timeout() { void test_timeout() {
CHECK(count > 0); CHECK(count > 0);
// we must yield scheduler, so run_main breaks immediately, if timeouts are handled immediately // 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) { TEST(MultiTimeout, Destroy) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
ConcurrentScheduler sched; td::ConcurrentScheduler sched;
int threads_n = 0; int threads_n = 0;
sched.init(threads_n); sched.init(threads_n);
ActorOwn<TimeoutManager> timeout_manager = sched.create_actor_unsafe<TimeoutManager>(0, "TimeoutManager"); auto timeout_manager = sched.create_actor_unsafe<TimeoutManager>(0, "TimeoutManager");
TimeoutManager *manager = timeout_manager.get().get_actor_unsafe(); TimeoutManager *manager = timeout_manager.get().get_actor_unsafe();
sched.start(); sched.start();
int cnt = 100; int cnt = 100;
@ -107,12 +105,12 @@ TEST(MultiTimeout, Destroy) {
cnt--; cnt--;
if (cnt > 0) { if (cnt > 0) {
for (int i = 0; i < 2; i++) { 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) { } else if (cnt == 0) {
timeout_manager.reset(); timeout_manager.reset();
} else if (cnt == -10) { } else if (cnt == -10) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
} }
sched.finish(); sched.finish();

View File

@ -19,18 +19,16 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
using namespace td;
namespace { namespace {
template <class ContainerT> template <class ContainerT>
static typename ContainerT::value_type &rand_elem(ContainerT &cont) { static typename ContainerT::value_type &rand_elem(ContainerT &cont) {
CHECK(0 < cont.size() && cont.size() <= static_cast<size_t>(std::numeric_limits<int>::max())); CHECK(0 < cont.size() && cont.size() <= static_cast<size_t>(std::numeric_limits<int>::max()));
return cont[Random::fast(0, static_cast<int>(cont.size()) - 1)]; return cont[td::Random::fast(0, static_cast<int>(cont.size()) - 1)];
} }
static uint32 fast_pow_mod_uint32(uint32 x, uint32 p) { static td::uint32 fast_pow_mod_uint32(td::uint32 x, td::uint32 p) {
uint32 res = 1; td::uint32 res = 1;
while (p) { while (p) {
if (p & 1) { if (p & 1) {
res *= x; res *= x;
@ -41,18 +39,18 @@ static uint32 fast_pow_mod_uint32(uint32 x, uint32 p) {
return res; return res;
} }
static uint32 slow_pow_mod_uint32(uint32 x, uint32 p) { static td::uint32 slow_pow_mod_uint32(td::uint32 x, td::uint32 p) {
uint32 res = 1; td::uint32 res = 1;
for (uint32 i = 0; i < p; i++) { for (td::uint32 i = 0; i < p; i++) {
res *= x; res *= x;
} }
return res; return res;
} }
struct Query { struct Query {
uint32 query_id{}; td::uint32 query_id{};
uint32 result{}; td::uint32 result{};
std::vector<int> todo; td::vector<int> todo;
Query() = default; Query() = default;
Query(const Query &) = delete; Query(const Query &) = delete;
Query &operator=(const Query &) = delete; Query &operator=(const Query &) = delete;
@ -72,25 +70,25 @@ struct Query {
} }
}; };
static uint32 fast_calc(Query &q) { static td::uint32 fast_calc(Query &q) {
uint32 result = q.result; td::uint32 result = q.result;
for (auto x : q.todo) { for (auto x : q.todo) {
result = fast_pow_mod_uint32(result, x); result = fast_pow_mod_uint32(result, x);
} }
return result; return result;
} }
class Worker final : public Actor { class Worker final : public td::Actor {
public: public:
explicit Worker(int threads_n) : threads_n_(threads_n) { explicit Worker(int threads_n) : threads_n_(threads_n) {
} }
void query(PromiseActor<uint32> &&promise, uint32 x, uint32 p) { void query(td::PromiseActor<td::uint32> &&promise, td::uint32 x, td::uint32 p) {
uint32 result = slow_pow_mod_uint32(x, p); td::uint32 result = slow_pow_mod_uint32(x, p);
promise.set_value(std::move(result)); promise.set_value(std::move(result));
(void)threads_n_; (void)threads_n_;
// if (threads_n_ > 1 && Random::fast(0, 9) == 0) { // if (threads_n_ > 1 && td::Random::fast(0, 9) == 0) {
// migrate(Random::fast(2, threads_n)); // migrate(td::Random::fast(2, threads_n));
//} //}
} }
@ -98,7 +96,7 @@ class Worker final : public Actor {
int threads_n_; int threads_n_;
}; };
class QueryActor final : public Actor { class QueryActor final : public td::Actor {
public: public:
class Callback { class Callback {
public: public:
@ -115,39 +113,39 @@ class QueryActor final : public Actor {
explicit QueryActor(int threads_n) : threads_n_(threads_n) { explicit QueryActor(int threads_n) : threads_n_(threads_n) {
} }
void set_callback(unique_ptr<Callback> callback) { void set_callback(td::unique_ptr<Callback> callback) {
callback_ = std::move(callback); callback_ = std::move(callback);
} }
void set_workers(std::vector<ActorId<Worker>> workers) { void set_workers(td::vector<td::ActorId<Worker>> workers) {
workers_ = std::move(workers); workers_ = std::move(workers);
} }
void query(Query &&query) { void query(Query &&query) {
uint32 x = query.result; td::uint32 x = query.result;
uint32 p = query.next_pow(); td::uint32 p = query.next_pow();
if (Random::fast(0, 3) && (p <= 1000 || workers_.empty())) { if (td::Random::fast(0, 3) && (p <= 1000 || workers_.empty())) {
query.result = slow_pow_mod_uint32(x, p); query.result = slow_pow_mod_uint32(x, p);
callback_->on_result(std::move(query)); callback_->on_result(std::move(query));
} else { } else {
auto future = Random::fast(0, 3) == 0 auto future = td::Random::fast(0, 3) == 0
? send_promise<ActorSendType::Immediate>(rand_elem(workers_), &Worker::query, x, p) ? td::send_promise<td::ActorSendType::Immediate>(rand_elem(workers_), &Worker::query, x, p)
: send_promise<ActorSendType::Later>(rand_elem(workers_), &Worker::query, x, p); : td::send_promise<td::ActorSendType::Later>(rand_elem(workers_), &Worker::query, x, p);
if (future.is_ready()) { if (future.is_ready()) {
query.result = future.move_as_ok(); query.result = future.move_as_ok();
callback_->on_result(std::move(query)); callback_->on_result(std::move(query));
} else { } 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; auto query_id = query.query_id;
pending_.emplace(query_id, std::make_pair(std::move(future), std::move(query))); pending_.emplace(query_id, std::make_pair(std::move(future), std::move(query)));
} }
} }
if (threads_n_ > 1 && Random::fast(0, 9) == 0) { if (threads_n_ > 1 && td::Random::fast(0, 9) == 0) {
migrate(Random::fast(2, threads_n_)); migrate(td::Random::fast(2, threads_n_));
} }
} }
void raw_event(const Event::Raw &event) final { void raw_event(const td::Event::Raw &event) final {
uint32 id = event.u32; td::uint32 id = event.u32;
auto it = pending_.find(id); auto it = pending_.find(id);
auto future = std::move(it->second.first); auto future = std::move(it->second.first);
auto query = std::move(it->second.second); auto query = std::move(it->second.second);
@ -162,7 +160,7 @@ class QueryActor final : public Actor {
stop(); stop();
} }
void on_start_migrate(int32 sched_id) final { void on_start_migrate(td::int32 sched_id) final {
for (auto &it : pending_) { for (auto &it : pending_) {
start_migrate(it.second.first, sched_id); start_migrate(it.second.first, sched_id);
} }
@ -174,13 +172,13 @@ class QueryActor final : public Actor {
} }
private: private:
unique_ptr<Callback> callback_; td::unique_ptr<Callback> callback_;
std::map<uint32, std::pair<FutureActor<uint32>, Query>> pending_; std::map<td::uint32, std::pair<td::FutureActor<td::uint32>, Query>> pending_;
std::vector<ActorId<Worker>> workers_; td::vector<td::ActorId<Worker>> workers_;
int threads_n_; int threads_n_;
}; };
class MainQueryActor final : public Actor { class MainQueryActor final : public td::Actor {
class QueryActorCallback final : public QueryActor::Callback { class QueryActorCallback final : public QueryActor::Callback {
public: public:
void on_result(Query &&query) final { void on_result(Query &&query) final {
@ -193,13 +191,13 @@ class MainQueryActor final : public Actor {
void on_closed() final { void on_closed() final {
send_closure(parent_id_, &MainQueryActor::on_closed); send_closure(parent_id_, &MainQueryActor::on_closed);
} }
QueryActorCallback(ActorId<MainQueryActor> parent_id, ActorId<QueryActor> next_solver) QueryActorCallback(td::ActorId<MainQueryActor> parent_id, td::ActorId<QueryActor> next_solver)
: parent_id_(parent_id), next_solver_(next_solver) { : parent_id_(parent_id), next_solver_(next_solver) {
} }
private: private:
ActorId<MainQueryActor> parent_id_; td::ActorId<MainQueryActor> parent_id_;
ActorId<QueryActor> next_solver_; td::ActorId<QueryActor> next_solver_;
}; };
const int ACTORS_CNT = 10; const int ACTORS_CNT = 10;
@ -212,22 +210,22 @@ class MainQueryActor final : public Actor {
void start_up() final { void start_up() final {
actors_.resize(ACTORS_CNT); actors_.resize(ACTORS_CNT);
for (auto &actor : actors_) { for (auto &actor : actors_) {
auto actor_ptr = make_unique<QueryActor>(threads_n_); auto actor_ptr = td::make_unique<QueryActor>(threads_n_);
actor = register_actor("QueryActor", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0) actor = register_actor("QueryActor", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0)
.release(); .release();
} }
workers_.resize(WORKERS_CNT); workers_.resize(WORKERS_CNT);
for (auto &worker : workers_) { for (auto &worker : workers_) {
auto actor_ptr = make_unique<Worker>(threads_n_); auto actor_ptr = td::make_unique<Worker>(threads_n_);
worker = worker = register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0)
register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0).release(); .release();
} }
for (int i = 0; i < ACTORS_CNT; i++) { for (int i = 0; i < ACTORS_CNT; i++) {
ref_cnt_++; ref_cnt_++;
send_closure(actors_[i], &QueryActor::set_callback, send_closure(actors_[i], &QueryActor::set_callback,
make_unique<QueryActorCallback>(actor_id(this), actors_[(i + 1) % ACTORS_CNT])); td::make_unique<QueryActorCallback>(actor_id(this), actors_[(i + 1) % ACTORS_CNT]));
send_closure(actors_[i], &QueryActor::set_workers, workers_); send_closure(actors_[i], &QueryActor::set_workers, workers_);
} }
yield(); yield();
@ -252,14 +250,14 @@ class MainQueryActor final : public Actor {
void on_closed() { void on_closed() {
ref_cnt_--; ref_cnt_--;
if (ref_cnt_ == 0) { if (ref_cnt_ == 0) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
} }
void wakeup() final { void wakeup() final {
int cnt = 100000; int cnt = 100000;
while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) { 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()); send_closure(rand_elem(actors_), &QueryActor::query, create_query());
} else { } else {
send_closure_later(rand_elem(actors_), &QueryActor::query, create_query()); send_closure_later(rand_elem(actors_), &QueryActor::query, create_query());
@ -276,9 +274,9 @@ class MainQueryActor final : public Actor {
} }
private: private:
std::map<uint32, uint32> expected_; std::map<td::uint32, td::uint32> expected_;
std::vector<ActorId<QueryActor>> actors_; td::vector<td::ActorId<QueryActor>> actors_;
std::vector<ActorId<Worker>> workers_; td::vector<td::ActorId<Worker>> workers_;
int out_cnt_ = 0; int out_cnt_ = 0;
int in_cnt_ = 0; int in_cnt_ = 0;
int query_id_ = 1; int query_id_ = 1;
@ -286,46 +284,47 @@ class MainQueryActor final : public Actor {
int threads_n_; int threads_n_;
}; };
class SimpleActor final : public Actor { class SimpleActor final : public td::Actor {
public: public:
explicit SimpleActor(int32 threads_n) : threads_n_(threads_n) { explicit SimpleActor(td::int32 threads_n) : threads_n_(threads_n) {
} }
void start_up() final { void start_up() final {
auto actor_ptr = make_unique<Worker>(threads_n_); auto actor_ptr = td::make_unique<Worker>(threads_n_);
worker_ = 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(); yield();
} }
void wakeup() final { void wakeup() final {
if (q_ == 100000) { if (q_ == 100000) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
stop(); stop();
return; return;
} }
q_++; q_++;
p_ = Random::fast_bool() ? 1 : 10000; p_ = td::Random::fast_bool() ? 1 : 10000;
auto future = Random::fast(0, 3) == 0 ? send_promise<ActorSendType::Immediate>(worker_, &Worker::query, q_, p_) auto future = td::Random::fast(0, 3) == 0
: send_promise<ActorSendType::Later>(worker_, &Worker::query, q_, p_); ? td::send_promise<td::ActorSendType::Immediate>(worker_, &Worker::query, q_, p_)
: td::send_promise<td::ActorSendType::Later>(worker_, &Worker::query, q_, p_);
if (future.is_ready()) { if (future.is_ready()) {
auto result = future.move_as_ok(); auto result = future.move_as_ok();
CHECK(result == fast_pow_mod_uint32(q_, p_)); CHECK(result == fast_pow_mod_uint32(q_, p_));
yield(); yield();
} else { } else {
future.set_event(EventCreator::raw(actor_id(), nullptr)); future.set_event(td::EventCreator::raw(actor_id(), nullptr));
future_ = std::move(future); future_ = std::move(future);
} }
// if (threads_n_ > 1 && Random::fast(0, 2) == 0) { // if (threads_n_ > 1 && td::Random::fast(0, 2) == 0) {
// migrate(Random::fast(1, threads_n)); // 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(); auto result = future_.move_as_ok();
CHECK(result == fast_pow_mod_uint32(q_, p_)); CHECK(result == fast_pow_mod_uint32(q_, p_));
yield(); yield();
} }
void on_start_migrate(int32 sched_id) final { void on_start_migrate(td::int32 sched_id) final {
start_migrate(future_, sched_id); start_migrate(future_, sched_id);
} }
void on_finish_migrate() final { void on_finish_migrate() final {
@ -333,25 +332,26 @@ class SimpleActor final : public Actor {
} }
private: private:
int32 threads_n_; td::int32 threads_n_;
ActorId<Worker> worker_; td::ActorId<Worker> worker_;
FutureActor<uint32> future_; td::FutureActor<td::uint32> future_;
uint32 q_ = 1; td::uint32 q_ = 1;
uint32 p_ = 0; td::uint32 p_ = 0;
}; };
} // namespace } // namespace
class SendToDead final : public Actor { class SendToDead final : public td::Actor {
public: public:
class Parent final : public Actor { class Parent final : public td::Actor {
public: 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 { 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) { if (ttl_ != 0) {
child_ = create_actor_on_scheduler<Parent>( child_ = td::create_actor_on_scheduler<Parent>(
"Child", Random::fast_uint32() % Scheduler::instance()->sched_count(), actor_shared(this), ttl_ - 1); "Child", td::Random::fast_uint32() % td::Scheduler::instance()->sched_count(), actor_shared(this),
ttl_ - 1);
} }
} }
void timeout_expired() final { void timeout_expired() final {
@ -359,29 +359,30 @@ class SendToDead final : public Actor {
} }
private: private:
ActorOwn<Parent> child_; td::ActorOwn<Parent> child_;
ActorShared<> parent_; td::ActorShared<> parent_;
int ttl_; int ttl_;
}; };
void start_up() final { void start_up() final {
for (int i = 0; i < 2000; i++) { for (int i = 0; i < 2000; i++) {
create_actor_on_scheduler<Parent>("Parent", Random::fast_uint32() % Scheduler::instance()->sched_count(), td::create_actor_on_scheduler<Parent>(
create_reference(), 4) "Parent", td::Random::fast_uint32() % td::Scheduler::instance()->sched_count(), create_reference(), 4)
.release(); .release();
} }
} }
ActorShared<> create_reference() { td::ActorShared<> create_reference() {
ref_cnt_++; ref_cnt_++;
return actor_shared(this); return actor_shared(this);
} }
void hangup_shared() final { void hangup_shared() final {
ref_cnt_--; ref_cnt_--;
if (ref_cnt_ == 0) { if (ref_cnt_ == 0) {
ttl_--; ttl_--;
if (ttl_ <= 0) { if (ttl_ <= 0) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
stop(); stop();
} else { } else {
start_up(); start_up();
@ -389,14 +390,14 @@ class SendToDead final : public Actor {
} }
} }
uint32 ttl_{50}; td::uint32 ttl_{50};
uint32 ref_cnt_{0}; td::uint32 ref_cnt_{0};
}; };
TEST(Actors, send_to_dead) { TEST(Actors, send_to_dead) {
//TODO: fix CHECK(storage_count_.load() == 0) //TODO: fix CHECK(storage_count_.load() == 0)
return; return;
ConcurrentScheduler sched; td::ConcurrentScheduler sched;
int threads_n = 5; int threads_n = 5;
sched.init(threads_n); sched.init(threads_n);
@ -409,9 +410,7 @@ TEST(Actors, send_to_dead) {
} }
TEST(Actors, main_simple) { TEST(Actors, main_simple) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler sched;
ConcurrentScheduler sched;
int threads_n = 3; int threads_n = 3;
sched.init(threads_n); sched.init(threads_n);
@ -424,9 +423,7 @@ TEST(Actors, main_simple) {
} }
TEST(Actors, main) { TEST(Actors, main) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler sched;
ConcurrentScheduler sched;
int threads_n = 9; int threads_n = 9;
sched.init(threads_n); sched.init(threads_n);
@ -438,23 +435,21 @@ TEST(Actors, main) {
sched.finish(); sched.finish();
} }
class DoAfterStop final : public Actor { class DoAfterStop final : public td::Actor {
public: public:
void loop() final { void loop() final {
ptr = make_unique<int>(10); ptr = td::make_unique<int>(10);
stop(); stop();
CHECK(*ptr == 10); CHECK(*ptr == 10);
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
private: private:
unique_ptr<int> ptr; td::unique_ptr<int> ptr;
}; };
TEST(Actors, do_after_stop) { TEST(Actors, do_after_stop) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler sched;
ConcurrentScheduler sched;
int threads_n = 0; int threads_n = 0;
sched.init(threads_n); sched.init(threads_n);
@ -466,9 +461,9 @@ TEST(Actors, do_after_stop) {
sched.finish(); sched.finish();
} }
class XContext final : public ActorContext { class XContext final : public td::ActorContext {
public: public:
int32 get_id() const final { td::int32 get_id() const final {
return 123456789; return 123456789;
} }
@ -481,12 +476,12 @@ class XContext final : public ActorContext {
int x = 1234; int x = 1234;
}; };
class WithXContext final : public Actor { class WithXContext final : public td::Actor {
public: public:
void start_up() final { void start_up() final {
auto old_context = set_context(std::make_shared<XContext>()); auto old_context = set_context(std::make_shared<XContext>());
} }
void f(unique_ptr<Guard> guard) { void f(td::unique_ptr<td::Guard> guard) {
} }
void close() { void close() {
stop(); stop();
@ -494,25 +489,23 @@ class WithXContext final : public Actor {
}; };
static void check_context() { static void check_context() {
auto ptr = static_cast<XContext *>(Scheduler::context()); auto ptr = static_cast<XContext *>(td::Scheduler::context());
CHECK(ptr); CHECK(ptr != nullptr);
ptr->validate(); ptr->validate();
} }
TEST(Actors, context_during_destruction) { TEST(Actors, context_during_destruction) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler sched;
ConcurrentScheduler sched;
int threads_n = 0; int threads_n = 0;
sched.init(threads_n); sched.init(threads_n);
{ {
auto guard = sched.get_main_guard(); auto guard = sched.get_main_guard();
auto with_context = create_actor<WithXContext>("WithXContext").release(); auto with_context = td::create_actor<WithXContext>("WithXContext").release();
send_closure(with_context, &WithXContext::f, create_lambda_guard([] { check_context(); })); send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { check_context(); }));
send_closure_later(with_context, &WithXContext::close); send_closure_later(with_context, &WithXContext::close);
send_closure(with_context, &WithXContext::f, create_lambda_guard([] { check_context(); })); send_closure(with_context, &WithXContext::f, td::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([] { td::Scheduler::instance()->finish(); }));
} }
sched.start(); sched.start();
while (sched.run_main(10)) { while (sched.run_main(10)) {

View File

@ -28,40 +28,38 @@
#include <tuple> #include <tuple>
namespace { namespace {
using namespace td;
static const size_t BUF_SIZE = 1024 * 1024; static const size_t BUF_SIZE = 1024 * 1024;
static char buf[BUF_SIZE]; static char buf[BUF_SIZE];
static char buf2[BUF_SIZE]; static char buf2[BUF_SIZE];
static StringBuilder sb(MutableSlice(buf, BUF_SIZE - 1)); static td::StringBuilder sb(td::MutableSlice(buf, BUF_SIZE - 1));
static StringBuilder sb2(MutableSlice(buf2, BUF_SIZE - 1)); static td::StringBuilder sb2(td::MutableSlice(buf2, BUF_SIZE - 1));
static auto create_queue() { static std::shared_ptr<td::MpscPollableQueue<td::EventFull>> create_queue() {
auto res = std::make_shared<MpscPollableQueue<EventFull>>(); auto res = std::make_shared<td::MpscPollableQueue<td::EventFull>>();
res->init(); res->init();
return res; return res;
} }
TEST(Actors, SendLater) { TEST(Actors, SendLater) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
sb.clear(); sb.clear();
Scheduler scheduler; td::Scheduler scheduler;
scheduler.init(0, {create_queue()}, nullptr); scheduler.init(0, {create_queue()}, nullptr);
auto guard = scheduler.get_guard(); auto guard = scheduler.get_guard();
class Worker final : public Actor { class Worker final : public td::Actor {
public: public:
void f() { void f() {
sb << "A"; sb << "A";
} }
}; };
auto id = create_actor<Worker>("Worker"); auto id = td::create_actor<Worker>("Worker");
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
send_closure(id, &Worker::f); td::send_closure(id, &Worker::f);
send_closure_later(id, &Worker::f); td::send_closure_later(id, &Worker::f);
send_closure(id, &Worker::f); td::send_closure(id, &Worker::f);
ASSERT_STREQ("A", sb.as_cslice().c_str()); 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()); ASSERT_STREQ("AAA", sb.as_cslice().c_str());
} }
@ -87,7 +85,7 @@ class X {
~X() = default; ~X() = default;
}; };
class XReceiver final : public Actor { class XReceiver final : public td::Actor {
public: public:
void by_const_ref(const X &) { void by_const_ref(const X &) {
sb << "[by_const_ref]"; sb << "[by_const_ref]";
@ -101,13 +99,12 @@ class XReceiver final : public Actor {
}; };
TEST(Actors, simple_pass_event_arguments) { TEST(Actors, simple_pass_event_arguments) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::Scheduler scheduler;
Scheduler scheduler;
scheduler.init(0, {create_queue()}, nullptr); scheduler.init(0, {create_queue()}, nullptr);
auto guard = scheduler.get_guard(); auto guard = scheduler.get_guard();
auto id = create_actor<XReceiver>("XR").release(); auto id = td::create_actor<XReceiver>("XR").release();
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
X x; X x;
@ -122,47 +119,47 @@ TEST(Actors, simple_pass_event_arguments) {
// Tmp-->ConstRef // Tmp-->ConstRef
sb.clear(); 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()); ASSERT_STREQ("[cnstr_default][by_const_ref]", sb.as_cslice().c_str());
// Tmp-->ConstRef (Delayed) // Tmp-->ConstRef (Delayed)
sb.clear(); sb.clear();
send_closure_later(id, &XReceiver::by_const_ref, X()); td::send_closure_later(id, &XReceiver::by_const_ref, X());
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
// LOG(ERROR) << sb.as_cslice(); // LOG(ERROR) << sb.as_cslice();
ASSERT_STREQ("[cnstr_default][cnstr_move][by_const_ref]", sb.as_cslice().c_str()); ASSERT_STREQ("[cnstr_default][cnstr_move][by_const_ref]", sb.as_cslice().c_str());
// Tmp-->LvalueRef // Tmp-->LvalueRef
sb.clear(); 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()); ASSERT_STREQ("[cnstr_default][by_lvalue_ref]", sb.as_cslice().c_str());
// Tmp-->LvalueRef (Delayed) // Tmp-->LvalueRef (Delayed)
sb.clear(); sb.clear();
send_closure_later(id, &XReceiver::by_lvalue_ref, X()); td::send_closure_later(id, &XReceiver::by_lvalue_ref, X());
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
ASSERT_STREQ("[cnstr_default][cnstr_move][by_lvalue_ref]", sb.as_cslice().c_str()); ASSERT_STREQ("[cnstr_default][cnstr_move][by_lvalue_ref]", sb.as_cslice().c_str());
// Tmp-->Value // Tmp-->Value
sb.clear(); 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()); ASSERT_STREQ("[cnstr_default][cnstr_move][by_value]", sb.as_cslice().c_str());
// Tmp-->Value (Delayed) // Tmp-->Value (Delayed)
sb.clear(); sb.clear();
send_closure_later(id, &XReceiver::by_value, X()); td::send_closure_later(id, &XReceiver::by_value, X());
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
ASSERT_STREQ("[cnstr_default][cnstr_move][cnstr_move][by_value]", sb.as_cslice().c_str()); ASSERT_STREQ("[cnstr_default][cnstr_move][cnstr_move][by_value]", sb.as_cslice().c_str());
// Var-->ConstRef // Var-->ConstRef
sb.clear(); 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()); ASSERT_STREQ("[by_const_ref]", sb.as_cslice().c_str());
// Var-->ConstRef (Delayed) // Var-->ConstRef (Delayed)
sb.clear(); sb.clear();
send_closure_later(id, &XReceiver::by_const_ref, x); td::send_closure_later(id, &XReceiver::by_const_ref, x);
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
ASSERT_STREQ("[cnstr_copy][by_const_ref]", sb.as_cslice().c_str()); ASSERT_STREQ("[cnstr_copy][by_const_ref]", sb.as_cslice().c_str());
// Var-->LvalueRef // Var-->LvalueRef
@ -171,17 +168,17 @@ TEST(Actors, simple_pass_event_arguments) {
// Var-->Value // Var-->Value
sb.clear(); 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()); ASSERT_STREQ("[cnstr_copy][by_value]", sb.as_cslice().c_str());
// Var-->Value (Delayed) // Var-->Value (Delayed)
sb.clear(); sb.clear();
send_closure_later(id, &XReceiver::by_value, x); td::send_closure_later(id, &XReceiver::by_value, x);
scheduler.run_no_guard(Timestamp::now()); scheduler.run_no_guard(td::Timestamp::in(1));
ASSERT_STREQ("[cnstr_copy][cnstr_move][by_value]", sb.as_cslice().c_str()); 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: public:
PrintChar(char c, int cnt) : char_(c), cnt_(cnt) { 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 // Yield must add actor to the end of queue
// //
TEST(Actors, simple_hand_yield) { TEST(Actors, simple_hand_yield) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::Scheduler scheduler;
Scheduler scheduler;
scheduler.init(0, {create_queue()}, nullptr); scheduler.init(0, {create_queue()}, nullptr);
sb.clear(); sb.clear();
int cnt = 1000; int cnt = 1000;
{ {
auto guard = scheduler.get_guard(); auto guard = scheduler.get_guard();
create_actor<PrintChar>("PrintA", 'A', cnt).release(); td::create_actor<PrintChar>("PrintA", 'A', cnt).release();
create_actor<PrintChar>("PrintB", 'B', cnt).release(); td::create_actor<PrintChar>("PrintB", 'B', cnt).release();
create_actor<PrintChar>("PrintC", 'C', cnt).release(); td::create_actor<PrintChar>("PrintC", 'C', cnt).release();
} }
scheduler.run(Timestamp::now()); scheduler.run(td::Timestamp::in(1));
std::string expected; td::string expected;
for (int i = 0; i < cnt; i++) { for (int i = 0; i < cnt; i++) {
expected += "ABC"; expected += "ABC";
} }
@ -229,7 +225,7 @@ TEST(Actors, simple_hand_yield) {
class Ball { class Ball {
public: public:
friend void start_migrate(Ball &ball, int32 sched_id) { friend void start_migrate(Ball &ball, td::int32 sched_id) {
sb << "start"; sb << "start";
} }
friend void finish_migrate(Ball &ball) { friend void finish_migrate(Ball &ball) {
@ -237,30 +233,30 @@ class Ball {
} }
}; };
class Pong final : public Actor { class Pong final : public td::Actor {
public: public:
void pong(Ball ball) { void pong(Ball ball) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
}; };
class Ping final : public Actor { class Ping final : public td::Actor {
public: public:
explicit Ping(ActorId<Pong> pong) : pong_(pong) { explicit Ping(td::ActorId<Pong> pong) : pong_(pong) {
} }
void start_up() final { void start_up() final {
send_closure(pong_, &Pong::pong, Ball()); td::send_closure(pong_, &Pong::pong, Ball());
} }
private: private:
ActorId<Pong> pong_; td::ActorId<Pong> pong_;
}; };
TEST(Actors, simple_migrate) { TEST(Actors, simple_migrate) {
sb.clear(); sb.clear();
sb2.clear(); sb2.clear();
ConcurrentScheduler scheduler; td::ConcurrentScheduler scheduler;
scheduler.init(2); scheduler.init(2);
auto pong = scheduler.create_actor_unsafe<Pong>(2, "Pong").release(); auto pong = scheduler.create_actor_unsafe<Pong>(2, "Pong").release();
scheduler.create_actor_unsafe<Ping>(1, "Ping", pong).release(); scheduler.create_actor_unsafe<Ping>(1, "Ping", pong).release();
@ -277,7 +273,7 @@ TEST(Actors, simple_migrate) {
#endif #endif
} }
class OpenClose final : public Actor { class OpenClose final : public td::Actor {
public: public:
explicit OpenClose(int cnt) : cnt_(cnt) { explicit OpenClose(int cnt) : cnt_(cnt) {
} }
@ -285,17 +281,17 @@ class OpenClose final : public Actor {
yield(); yield();
} }
void wakeup() final { void wakeup() final {
ObserverBase *observer = reinterpret_cast<ObserverBase *>(123); auto observer = reinterpret_cast<td::ObserverBase *>(123);
if (cnt_ > 0) { 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(); LOG_CHECK(r_file_fd.is_ok()) << r_file_fd.error();
auto file_fd = r_file_fd.move_as_ok(); 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(); file_fd.close();
cnt_--; cnt_--;
yield(); yield();
} else { } else {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
} }
@ -304,8 +300,7 @@ class OpenClose final : public Actor {
}; };
TEST(Actors, open_close) { TEST(Actors, open_close) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
ConcurrentScheduler scheduler;
scheduler.init(2); scheduler.init(2);
int cnt = 1000000; int cnt = 1000000;
#if TD_WINDOWS || TD_ANDROID #if TD_WINDOWS || TD_ANDROID
@ -321,18 +316,18 @@ TEST(Actors, open_close) {
} }
namespace { namespace {
class MsgActor : public Actor { class MsgActor : public td::Actor {
public: public:
virtual void msg() = 0; virtual void msg() = 0;
}; };
class Slave final : public Actor { class Slave final : public td::Actor {
public: public:
ActorId<MsgActor> msg; td::ActorId<MsgActor> msg;
explicit Slave(ActorId<MsgActor> msg) : msg(msg) { explicit Slave(td::ActorId<MsgActor> msg) : msg(msg) {
} }
void hangup() final { void hangup() final {
send_closure(msg, &MsgActor::msg); td::send_closure(msg, &MsgActor::msg);
} }
}; };
@ -340,10 +335,10 @@ class MasterActor final : public MsgActor {
public: public:
void loop() final { void loop() final {
alive_ = true; alive_ = true;
slave = create_actor<Slave>("slave", static_cast<ActorId<MsgActor>>(actor_id(this))); slave = td::create_actor<Slave>("slave", static_cast<td::ActorId<MsgActor>>(actor_id(this)));
stop(); stop();
} }
ActorOwn<Slave> slave; td::ActorOwn<Slave> slave;
MasterActor() = default; MasterActor() = default;
MasterActor(const MasterActor &) = delete; MasterActor(const MasterActor &) = delete;
@ -356,26 +351,25 @@ class MasterActor final : public MsgActor {
void msg() final { void msg() final {
CHECK(alive_ == 123456789); CHECK(alive_ == 123456789);
} }
uint64 alive_ = 123456789; td::uint64 alive_ = 123456789;
}; };
} // namespace } // namespace
TEST(Actors, call_after_destruct) { TEST(Actors, call_after_destruct) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::Scheduler scheduler;
Scheduler scheduler;
scheduler.init(0, {create_queue()}, nullptr); scheduler.init(0, {create_queue()}, nullptr);
{ {
auto guard = scheduler.get_guard(); auto guard = scheduler.get_guard();
create_actor<MasterActor>("Master").release(); td::create_actor<MasterActor>("Master").release();
} }
scheduler.run(Timestamp::now()); scheduler.run(td::Timestamp::in(1));
} }
class LinkTokenSlave final : public Actor { class LinkTokenSlave final : public td::Actor {
public: 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()); CHECK(link_token == get_link_token());
} }
void close() { void close() {
@ -383,42 +377,43 @@ class LinkTokenSlave final : public Actor {
} }
private: private:
ActorShared<> parent_; td::ActorShared<> parent_;
}; };
class LinkTokenMasterActor final : public Actor { class LinkTokenMasterActor final : public td::Actor {
public: public:
explicit LinkTokenMasterActor(int cnt) : cnt_(cnt) { explicit LinkTokenMasterActor(int cnt) : cnt_(cnt) {
} }
void start_up() final { void start_up() final {
child_ = create_actor<LinkTokenSlave>("Slave", actor_shared(this, 123)).release(); child_ = td::create_actor<LinkTokenSlave>("Slave", actor_shared(this, 123)).release();
yield(); yield();
} }
void loop() final { void loop() final {
for (int i = 0; i < 100 && cnt_ > 0; cnt_--, i++) { for (int i = 0; i < 100 && cnt_ > 0; cnt_--, i++) {
auto token = static_cast<uint64>(cnt_) + 1; auto token = static_cast<td::uint64>(cnt_) + 1;
switch (i % 4) { switch (i % 4) {
case 0: { case 0: {
send_closure(ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token); td::send_closure(td::ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token);
break; break;
} }
case 1: { case 1: {
send_closure_later(ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token); td::send_closure_later(td::ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token);
break; break;
} }
case 2: { case 2: {
EventCreator::closure(ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token).try_emit(); td::EventCreator::closure(td::ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token)
.try_emit();
break; break;
} }
case 3: { case 3: {
EventCreator::closure(ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token) td::EventCreator::closure(td::ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token)
.try_emit_later(); .try_emit_later();
break; break;
} }
} }
} }
if (cnt_ == 0) { if (cnt_ == 0) {
send_closure(child_, &LinkTokenSlave::close); td::send_closure(child_, &LinkTokenSlave::close);
} else { } else {
yield(); yield();
} }
@ -426,18 +421,17 @@ class LinkTokenMasterActor final : public Actor {
void hangup_shared() final { void hangup_shared() final {
CHECK(get_link_token() == 123); CHECK(get_link_token() == 123);
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
stop(); stop();
} }
private: private:
int cnt_; int cnt_;
ActorId<LinkTokenSlave> child_; td::ActorId<LinkTokenSlave> child_;
}; };
TEST(Actors, link_token) { TEST(Actors, link_token) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
ConcurrentScheduler scheduler;
scheduler.init(0); scheduler.init(0);
auto cnt = 100000; auto cnt = 100000;
scheduler.create_actor_unsafe<LinkTokenMasterActor>(0, "A", cnt).release(); scheduler.create_actor_unsafe<LinkTokenMasterActor>(0, "A", cnt).release();
@ -449,25 +443,25 @@ TEST(Actors, link_token) {
TEST(Actors, promise) { TEST(Actors, promise) {
int value = -1; int value = -1;
Promise<int> p1 = PromiseCreator::lambda([&](int x) { value = x; }); td::Promise<int> p1 = td::PromiseCreator::lambda([&](int x) { value = x; });
p1.set_error(Status::Error("Test error")); p1.set_error(td::Status::Error("Test error"));
ASSERT_EQ(0, value); ASSERT_EQ(0, value);
Promise<int32> p2 = PromiseCreator::lambda([&](Result<int32> x) { value = 1; }); td::Promise<td::int32> p2 = td::PromiseCreator::lambda([&](td::Result<td::int32> x) { value = 1; });
p2.set_error(Status::Error("Test error")); p2.set_error(td::Status::Error("Test error"));
ASSERT_EQ(1, value); ASSERT_EQ(1, value);
} }
class LaterSlave final : public Actor { class LaterSlave final : public td::Actor {
public: public:
explicit LaterSlave(ActorShared<> parent) : parent_(std::move(parent)) { explicit LaterSlave(td::ActorShared<> parent) : parent_(std::move(parent)) {
} }
private: private:
ActorShared<> parent_; td::ActorShared<> parent_;
void hangup() final { void hangup() final {
sb << "A"; sb << "A";
send_closure(actor_id(this), &LaterSlave::finish); td::send_closure(actor_id(this), &LaterSlave::finish);
} }
void finish() { void finish() {
sb << "B"; 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; int cnt_ = 3;
std::vector<ActorOwn<LaterSlave>> children_; td::vector<td::ActorOwn<LaterSlave>> children_;
void start_up() final { void start_up() final {
for (int i = 0; i < cnt_; i++) { for (int i = 0; i < cnt_; i++) {
children_.push_back(create_actor<LaterSlave>("B", actor_shared(this))); children_.push_back(td::create_actor<LaterSlave>("B", actor_shared(this)));
} }
yield(); yield();
} }
@ -489,16 +483,15 @@ class LaterMasterActor final : public Actor {
} }
void hangup_shared() final { void hangup_shared() final {
if (!--cnt_) { if (!--cnt_) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
stop(); stop();
} }
} }
}; };
TEST(Actors, later) { TEST(Actors, later) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
sb.clear(); sb.clear();
ConcurrentScheduler scheduler; td::ConcurrentScheduler scheduler;
scheduler.init(0); scheduler.init(0);
scheduler.create_actor_unsafe<LaterMasterActor>(0, "A").release(); scheduler.create_actor_unsafe<LaterMasterActor>(0, "A").release();
scheduler.start(); scheduler.start();
@ -508,38 +501,36 @@ TEST(Actors, later) {
ASSERT_STREQ(sb.as_cslice().c_str(), "AAABBB"); ASSERT_STREQ(sb.as_cslice().c_str(), "AAABBB");
} }
class MultiPromise2 final : public Actor { class MultiPromise2 final : public td::Actor {
public: public:
void start_up() final { void start_up() final {
auto promise = PromiseCreator::lambda([](Result<Unit> result) { auto promise = td::PromiseCreator::lambda([](td::Result<td::Unit> result) {
result.ensure(); 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)); multi_promise.add_promise(std::move(promise));
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
create_actor<SleepActor>("Sleep", 0.1, multi_promise.get_promise()).release(); td::create_actor<td::SleepActor>("Sleep", 0.1, multi_promise.get_promise()).release();
} }
} }
}; };
class MultiPromise1 final : public Actor { class MultiPromise1 final : public td::Actor {
public: public:
void start_up() final { void start_up() final {
auto promise = PromiseCreator::lambda([](Result<Unit> result) { auto promise = td::PromiseCreator::lambda([](td::Result<td::Unit> result) {
CHECK(result.is_error()); CHECK(result.is_error());
create_actor<MultiPromise2>("B").release(); td::create_actor<MultiPromise2>("B").release();
}); });
MultiPromiseActorSafe multi_promise{"MultiPromiseActor1"}; td::MultiPromiseActorSafe multi_promise{"MultiPromiseActor1"};
multi_promise.add_promise(std::move(promise)); multi_promise.add_promise(std::move(promise));
} }
}; };
TEST(Actors, MultiPromise) { TEST(Actors, MultiPromise) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
sb.clear();
ConcurrentScheduler scheduler;
scheduler.init(0); scheduler.init(0);
scheduler.create_actor_unsafe<MultiPromise1>(0, "A").release(); scheduler.create_actor_unsafe<MultiPromise1>(0, "A").release();
scheduler.start(); scheduler.start();
@ -548,22 +539,20 @@ TEST(Actors, MultiPromise) {
scheduler.finish(); scheduler.finish();
} }
class FastPromise final : public Actor { class FastPromise final : public td::Actor {
public: public:
void start_up() final { void start_up() final {
PromiseFuture<int> pf; td::PromiseFuture<int> pf;
auto promise = pf.move_promise(); auto promise = pf.move_promise();
auto future = pf.move_future(); auto future = pf.move_future();
promise.set_value(123); promise.set_value(123);
CHECK(future.move_as_ok() == 123); CHECK(future.move_as_ok() == 123);
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
}; };
TEST(Actors, FastPromise) { TEST(Actors, FastPromise) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
sb.clear();
ConcurrentScheduler scheduler;
scheduler.init(0); scheduler.init(0);
scheduler.create_actor_unsafe<FastPromise>(0, "A").release(); scheduler.create_actor_unsafe<FastPromise>(0, "A").release();
scheduler.start(); scheduler.start();
@ -572,20 +561,18 @@ TEST(Actors, FastPromise) {
scheduler.finish(); scheduler.finish();
} }
class StopInTeardown final : public Actor { class StopInTeardown final : public td::Actor {
void loop() final { void loop() final {
stop(); stop();
} }
void tear_down() final { void tear_down() final {
stop(); stop();
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
}; };
TEST(Actors, stop_in_teardown) { TEST(Actors, stop_in_teardown) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
sb.clear();
ConcurrentScheduler scheduler;
scheduler.init(0); scheduler.init(0);
scheduler.create_actor_unsafe<StopInTeardown>(0, "A").release(); scheduler.create_actor_unsafe<StopInTeardown>(0, "A").release();
scheduler.start(); scheduler.start();
@ -594,34 +581,33 @@ TEST(Actors, stop_in_teardown) {
scheduler.finish(); scheduler.finish();
} }
class AlwaysWaitForMailbox final : public Actor { class AlwaysWaitForMailbox final : public td::Actor {
public: public:
void start_up() final { void start_up() final {
always_wait_for_mailbox(); always_wait_for_mailbox();
create_actor<SleepActor>("Sleep", 0.1, PromiseCreator::lambda([actor_id = actor_id(this), ptr = this](Unit) { td::create_actor<td::SleepActor>("Sleep", 0.1,
send_closure(actor_id, &AlwaysWaitForMailbox::g); td::PromiseCreator::lambda([actor_id = actor_id(this), ptr = this](td::Unit) {
send_closure(actor_id, &AlwaysWaitForMailbox::g); td::send_closure(actor_id, &AlwaysWaitForMailbox::g);
CHECK(!ptr->was_f_); td::send_closure(actor_id, &AlwaysWaitForMailbox::g);
})) CHECK(!ptr->was_f_);
}))
.release(); .release();
} }
void f() { void f() {
was_f_ = true; was_f_ = true;
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
} }
void g() { void g() {
send_closure(actor_id(this), &AlwaysWaitForMailbox::f); td::send_closure(actor_id(this), &AlwaysWaitForMailbox::f);
} }
private: private:
Timeout timeout_;
bool was_f_{false}; bool was_f_{false};
}; };
TEST(Actors, always_wait_for_mailbox) { TEST(Actors, always_wait_for_mailbox) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
ConcurrentScheduler scheduler;
scheduler.init(0); scheduler.init(0);
scheduler.create_actor_unsafe<AlwaysWaitForMailbox>(0, "A").release(); scheduler.create_actor_unsafe<AlwaysWaitForMailbox>(0, "A").release();
scheduler.start(); scheduler.start();
@ -632,17 +618,16 @@ TEST(Actors, always_wait_for_mailbox) {
#if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED #if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED
TEST(Actors, send_from_other_threads) { TEST(Actors, send_from_other_threads) {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR)); td::ConcurrentScheduler scheduler;
ConcurrentScheduler scheduler;
scheduler.init(1); scheduler.init(1);
int thread_n = 10; int thread_n = 10;
class Listener final : public Actor { class Listener final : public td::Actor {
public: public:
explicit Listener(int cnt) : cnt_(cnt) { explicit Listener(int cnt) : cnt_(cnt) {
} }
void dec() { void dec() {
if (--cnt_ == 0) { 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<Listener>(1, "A", thread_n).release(); auto A = scheduler.create_actor_unsafe<Listener>(1, "A", thread_n).release();
scheduler.start(); scheduler.start();
std::vector<td::thread> threads(thread_n); td::vector<td::thread> threads(thread_n);
for (auto &thread : threads) { for (auto &thread : threads) {
thread = td::thread([&A, &scheduler] { thread = td::thread([&A, &scheduler] {
auto guard = scheduler.get_send_guard(); auto guard = scheduler.get_send_guard();
send_closure(A, &Listener::dec); td::send_closure(A, &Listener::dec);
}); });
} }
while (scheduler.run_main(10)) { while (scheduler.run_main(10)) {
@ -667,3 +652,45 @@ TEST(Actors, send_from_other_threads) {
scheduler.finish(); scheduler.finish();
} }
#endif #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>("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<DelayedCall> delayed_call_;
};
TEST(Actors, MultiPromiseSendClosureLater) {
td::ConcurrentScheduler scheduler;
scheduler.init(0);
scheduler.create_actor_unsafe<MultiPromiseSendClosureLaterTest>(0, "MultiPromiseSendClosureLaterTest").release();
scheduler.start();
while (scheduler.run_main(1)) {
}
scheduler.finish();
}

View File

@ -12,9 +12,7 @@
namespace { namespace {
using namespace td; class PowerWorker final : public td::Actor {
class PowerWorker final : public Actor {
public: public:
class Callback { class Callback {
public: public:
@ -27,12 +25,12 @@ class PowerWorker final : public Actor {
virtual void on_ready(int query, int res) = 0; virtual void on_ready(int query, int res) = 0;
virtual void on_closed() = 0; virtual void on_closed() = 0;
}; };
void set_callback(unique_ptr<Callback> callback) { void set_callback(td::unique_ptr<Callback> callback) {
callback_ = std::move(callback); callback_ = std::move(callback);
} }
void task(uint32 x, uint32 p) { void task(td::uint32 x, td::uint32 p) {
uint32 res = 1; td::uint32 res = 1;
for (uint32 i = 0; i < p; i++) { for (td::uint32 i = 0; i < p; i++) {
res *= x; res *= x;
} }
callback_->on_ready(x, res); callback_->on_ready(x, res);
@ -43,12 +41,12 @@ class PowerWorker final : public Actor {
} }
private: private:
unique_ptr<Callback> callback_; td::unique_ptr<Callback> callback_;
}; };
class Manager final : public Actor { class Manager final : public td::Actor {
public: public:
Manager(int queries_n, int query_size, std::vector<ActorId<PowerWorker>> workers) Manager(int queries_n, int query_size, td::vector<td::ActorId<PowerWorker>> workers)
: workers_(std::move(workers)) : workers_(std::move(workers))
, ref_cnt_(static_cast<int>(workers_.size())) , ref_cnt_(static_cast<int>(workers_.size()))
, left_query_(queries_n) , left_query_(queries_n)
@ -57,17 +55,17 @@ class Manager final : public Actor {
class Callback final : public PowerWorker::Callback { class Callback final : public PowerWorker::Callback {
public: public:
Callback(ActorId<Manager> actor_id, int worker_id) : actor_id_(actor_id), worker_id_(worker_id) { Callback(td::ActorId<Manager> actor_id, int worker_id) : actor_id_(actor_id), worker_id_(worker_id) {
} }
void on_ready(int query, int result) final { 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 { 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: private:
ActorId<Manager> actor_id_; td::ActorId<Manager> actor_id_;
int worker_id_; int worker_id_;
}; };
@ -75,9 +73,9 @@ class Manager final : public Actor {
int i = 0; int i = 0;
for (auto &worker : workers_) { for (auto &worker : workers_) {
ref_cnt_++; ref_cnt_++;
send_closure_later(worker, &PowerWorker::set_callback, make_unique<Callback>(actor_id(this), i)); td::send_closure_later(worker, &PowerWorker::set_callback, td::make_unique<Callback>(actor_id(this), i));
i++; i++;
send_closure_later(worker, &PowerWorker::task, 3, query_size_); td::send_closure_later(worker, &PowerWorker::task, 3, query_size_);
left_query_--; left_query_--;
} }
} }
@ -85,10 +83,10 @@ class Manager final : public Actor {
void on_ready(int worker_id, int query, int res) { void on_ready(int worker_id, int query, int res) {
ref_cnt_--; ref_cnt_--;
if (left_query_ == 0) { if (left_query_ == 0) {
send_closure(workers_[worker_id], &PowerWorker::close); td::send_closure(workers_[worker_id], &PowerWorker::close);
} else { } else {
ref_cnt_++; 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_--; left_query_--;
} }
} }
@ -96,23 +94,23 @@ class Manager final : public Actor {
void on_closed(int worker_id) { void on_closed(int worker_id) {
ref_cnt_--; ref_cnt_--;
if (ref_cnt_ == 0) { if (ref_cnt_ == 0) {
Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
stop(); stop();
} }
} }
private: private:
std::vector<ActorId<PowerWorker>> workers_; td::vector<td::ActorId<PowerWorker>> workers_;
int ref_cnt_; int ref_cnt_;
int left_query_; int left_query_;
int query_size_; int query_size_;
}; };
static void test_workers(int threads_n, int workers_n, int queries_n, 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); sched.init(threads_n);
std::vector<ActorId<PowerWorker>> workers; td::vector<td::ActorId<PowerWorker>> workers;
for (int i = 0; i < workers_n; i++) { for (int i = 0; i < workers_n; i++) {
int thread_id = threads_n ? i % (threads_n - 1) + 2 : 0; int thread_id = threads_n ? i % (threads_n - 1) + 2 : 0;
workers.push_back(sched.create_actor_unsafe<PowerWorker>(thread_id, PSLICE() << "worker" << i).release()); workers.push_back(sched.create_actor_unsafe<PowerWorker>(thread_id, PSLICE() << "worker" << i).release());

View File

@ -175,13 +175,20 @@ Status SqliteDb::set_user_version(int32 version) {
return exec(PSLICE() << "PRAGMA user_version = " << version); return exec(PSLICE() << "PRAGMA user_version = " << version);
} }
Status SqliteDb::begin_transaction() { Status SqliteDb::begin_read_transaction() {
if (raw_->on_begin()) { if (raw_->on_begin()) {
return exec("BEGIN"); return exec("BEGIN");
} }
return Status::OK(); return Status::OK();
} }
Status SqliteDb::begin_write_transaction() {
if (raw_->on_begin()) {
return exec("BEGIN IMMEDIATE");
}
return Status::OK();
}
Status SqliteDb::commit_transaction() { Status SqliteDb::commit_transaction() {
TRY_RESULT(need_commit, raw_->on_commit()); TRY_RESULT(need_commit, raw_->on_commit());
if (need_commit) { if (need_commit) {

View File

@ -46,7 +46,9 @@ class SqliteDb {
Result<bool> has_table(Slice table); Result<bool> has_table(Slice table);
Result<string> get_pragma(Slice name); Result<string> get_pragma(Slice name);
Result<string> get_pragma_string(Slice name); Result<string> 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; Status commit_transaction() TD_WARN_UNUSED_RESULT;
Result<int32> user_version(); Result<int32> user_version();

View File

@ -51,8 +51,11 @@ class SqliteKeyValue {
SeqNo erase(Slice key); SeqNo erase(Slice key);
Status begin_transaction() TD_WARN_UNUSED_RESULT { Status begin_read_transaction() TD_WARN_UNUSED_RESULT {
return db_.begin_transaction(); 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 { Status commit_transaction() TD_WARN_UNUSED_RESULT {
return db_.commit_transaction(); return db_.commit_transaction();

View File

@ -121,7 +121,7 @@ class SqliteKeyValueAsync final : public SqliteKeyValueAsyncInterface {
wakeup_at_ = 0; wakeup_at_ = 0;
cnt_ = 0; cnt_ = 0;
kv_->begin_transaction().ensure(); kv_->begin_write_transaction().ensure();
for (auto &it : buffer_) { for (auto &it : buffer_) {
if (it.second) { if (it.second) {
kv_->set(it.first, it.second.value()); kv_->set(it.first, it.second.value());

View File

@ -150,7 +150,9 @@ Slice get_operating_system_version() {
} }
var clientStrings = [ 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.1', r:/(Windows 8.1|Windows NT 6.3)/},
{s:'Windows 8', r:/(Windows 8|Windows NT 6.2)/}, {s:'Windows 8', r:/(Windows 8|Windows NT 6.2)/},
{s:'Windows 7', r:/(Windows 7|Windows NT 6.1)/}, {s:'Windows 7', r:/(Windows 7|Windows NT 6.1)/},
@ -242,7 +244,18 @@ Slice get_operating_system_version() {
if (major == 10) { if (major == 10) {
if (is_server) { 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"; return "Windows 10";
} }

View File

@ -58,7 +58,7 @@ TEST(EpochBaseMemoryReclamation, stress) {
for (auto &thread : threads) { for (auto &thread : threads) {
thread.join(); thread.join();
} }
LOG(ERROR) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe(); LOG(INFO) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe();
//CHECK(static_cast<int>(ebmr.to_delete_size_unsafe()) <= threads_n * threads_n); //CHECK(static_cast<int>(ebmr.to_delete_size_unsafe()) <= threads_n * threads_n);
for (int i = 0; i < threads_n; i++) { for (int i = 0; i < threads_n; i++) {
ebmr.get_locker(i).retire_sync(); ebmr.get_locker(i).retire_sync();

View File

@ -50,7 +50,7 @@ TEST(HazardPointers, stress) {
for (auto &thread : threads) { for (auto &thread : threads) {
thread.join(); 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<int>(hazard_pointers.to_delete_size_unsafe()) <= threads_n * threads_n); CHECK(static_cast<int>(hazard_pointers.to_delete_size_unsafe()) <= threads_n * threads_n);
for (int i = 0; i < threads_n; i++) { for (int i = 0; i < threads_n; i++) {
hazard_pointers.retire(i); hazard_pointers.retire(i);

View File

@ -9,47 +9,45 @@
#include "td/utils/buffer.h" #include "td/utils/buffer.h"
#include "td/utils/Random.h" #include "td/utils/Random.h"
using namespace td;
TEST(Buffer, buffer_builder) { TEST(Buffer, buffer_builder) {
{ {
BufferBuilder builder; td::BufferBuilder builder;
builder.append("b"); builder.append("b");
builder.prepend("a"); builder.prepend("a");
builder.append("c"); builder.append("c");
ASSERT_EQ(builder.extract().as_slice(), "abc"); 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"); ASSERT_EQ(builder.extract().as_slice(), "hello");
} }
{ {
BufferBuilder builder{"hello", 1, 1}; td::BufferBuilder builder{"hello", 1, 1};
builder.prepend("A "); builder.prepend("A ");
builder.append(" B"); builder.append(" B");
ASSERT_EQ(builder.extract().as_slice(), "A hello B"); ASSERT_EQ(builder.extract().as_slice(), "A hello B");
} }
{ {
std::string str = rand_string('a', 'z', 10000); auto str = td::rand_string('a', 'z', 10000);
auto splitted_str = rand_split(str); auto splitted_str = td::rand_split(str);
int l = Random::fast(0, static_cast<int32>(splitted_str.size() - 1)); int l = td::Random::fast(0, static_cast<int>(splitted_str.size() - 1));
int r = l; int r = l;
BufferBuilder builder(splitted_str[l], 123, 1000); td::BufferBuilder builder(splitted_str[l], 123, 1000);
while (l != 0 || r != static_cast<int32>(splitted_str.size()) - 1) { while (l != 0 || r != static_cast<int>(splitted_str.size()) - 1) {
if (l == 0 || (Random::fast_bool() && r != static_cast<int32>(splitted_str.size() - 1))) { if (l == 0 || (td::Random::fast_bool() && r != static_cast<int>(splitted_str.size() - 1))) {
r++; r++;
if (Random::fast_bool()) { if (td::Random::fast_bool()) {
builder.append(splitted_str[r]); builder.append(splitted_str[r]);
} else { } else {
builder.append(BufferSlice(splitted_str[r])); builder.append(td::BufferSlice(splitted_str[r]));
} }
} else { } else {
l--; l--;
if (Random::fast_bool()) { if (td::Random::fast_bool()) {
builder.prepend(splitted_str[l]); builder.prepend(splitted_str[l]);
} else { } else {
builder.prepend(BufferSlice(splitted_str[l])); builder.prepend(td::BufferSlice(splitted_str[l]));
} }
} }
} }

View File

@ -12,17 +12,15 @@
#include <utility> #include <utility>
using namespace td; static void decode_encode(td::string str, td::string result = "") {
static void decode_encode(string str, string result = "") {
auto str_copy = str; 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()); ASSERT_TRUE(r_value.is_ok());
if (r_value.is_error()) { if (r_value.is_error()) {
LOG(INFO) << r_value.error(); LOG(INFO) << r_value.error();
return; return;
} }
auto new_str = json_encode<string>(r_value.ok()); auto new_str = td::json_encode<td::string>(r_value.ok());
if (result.empty()) { if (result.empty()) {
result = str; result = str;
} }
@ -31,18 +29,19 @@ static void decode_encode(string str, string result = "") {
TEST(JSON, array) { TEST(JSON, array) {
char tmp[1000]; char tmp[1000];
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)});
JsonBuilder jb(std::move(sb)); td::JsonBuilder jb(std::move(sb));
jb.enter_value().enter_array() << "Hello" << -123; jb.enter_value().enter_array() << "Hello" << -123;
ASSERT_EQ(jb.string_builder().is_error(), false); ASSERT_EQ(jb.string_builder().is_error(), false);
auto encoded = jb.string_builder().as_cslice().str(); auto encoded = jb.string_builder().as_cslice().str();
ASSERT_EQ("[\"Hello\",-123]", encoded); ASSERT_EQ("[\"Hello\",-123]", encoded);
decode_encode(encoded); decode_encode(encoded);
} }
TEST(JSON, object) { TEST(JSON, object) {
char tmp[1000]; char tmp[1000];
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)});
JsonBuilder jb(std::move(sb)); td::JsonBuilder jb(std::move(sb));
auto c = jb.enter_object(); auto c = jb.enter_object();
c("key", "value"); c("key", "value");
c("1", 2); c("1", 2);
@ -55,8 +54,8 @@ TEST(JSON, object) {
TEST(JSON, nested) { TEST(JSON, nested) {
char tmp[1000]; char tmp[1000];
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)}); td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)});
JsonBuilder jb(std::move(sb)); td::JsonBuilder jb(std::move(sb));
{ {
auto a = jb.enter_array(); auto a = jb.enter_array();
a << 1; a << 1;

View File

@ -18,11 +18,9 @@
#include <limits> #include <limits>
#include <utility> #include <utility>
using namespace td;
#if TD_HAVE_OPENSSL #if TD_HAVE_OPENSSL
static bool is_prime(uint64 x) { static bool is_prime(td::uint64 x) {
for (uint64 d = 2; d < x && d * d <= x; d++) { for (td::uint64 d = 2; d < x && d * d <= x; d++) {
if (x % d == 0) { if (x % d == 0) {
return false; return false;
} }
@ -30,8 +28,8 @@ static bool is_prime(uint64 x) {
return true; return true;
} }
static std::vector<uint64> gen_primes(uint64 L, uint64 R, int limit = 0) { static td::vector<td::uint64> gen_primes(td::uint64 L, td::uint64 R, int limit = 0) {
std::vector<uint64> res; td::vector<td::uint64> res;
for (auto x = L; x <= R && (limit <= 0 || res.size() < static_cast<std::size_t>(limit)); x++) { for (auto x = L; x <= R && (limit <= 0 || res.size() < static_cast<std::size_t>(limit)); x++) {
if (is_prime(x)) { if (is_prime(x)) {
res.push_back(x); res.push_back(x);
@ -40,21 +38,23 @@ static std::vector<uint64> gen_primes(uint64 L, uint64 R, int limit = 0) {
return res; return res;
} }
static std::vector<uint64> gen_primes() { static td::vector<td::uint64> gen_primes() {
std::vector<uint64> result; td::vector<td::uint64> result;
append(result, gen_primes(1, 100)); td::append(result, gen_primes(1, 100));
append(result, gen_primes((1ull << 31) - 500000, std::numeric_limits<uint64>::max(), 5)); td::append(result, gen_primes((1ull << 31) - 500000, std::numeric_limits<td::uint64>::max(), 5));
append(result, gen_primes((1ull << 32) - 500000, std::numeric_limits<uint64>::max(), 5)); td::append(result, gen_primes((1ull << 32) - 500000, std::numeric_limits<td::uint64>::max(), 5));
append(result, gen_primes((1ull << 39) - 500000, std::numeric_limits<uint64>::max(), 1)); td::append(result, gen_primes((1ull << 39) - 500000, std::numeric_limits<td::uint64>::max(), 1));
return result; return result;
} }
using PqQuery = std::pair<uint64, uint64>; using PqQuery = std::pair<td::uint64, td::uint64>;
static bool cmp(const PqQuery &a, const PqQuery &b) { static bool cmp(const PqQuery &a, const PqQuery &b) {
return a.first * a.second < b.first * b.second; return a.first * a.second < b.first * b.second;
} }
static std::vector<PqQuery> gen_pq_queries() {
std::vector<PqQuery> res; static td::vector<PqQuery> gen_pq_queries() {
td::vector<PqQuery> res;
auto primes = gen_primes(); auto primes = gen_primes();
for (auto q : primes) { for (auto q : primes) {
for (auto p : primes) { for (auto p : primes) {
@ -68,21 +68,21 @@ static std::vector<PqQuery> gen_pq_queries() {
return res; return res;
} }
static void test_pq(uint64 first, uint64 second) { static void test_pq(td::uint64 first, td::uint64 second) {
BigNum p = BigNum::from_decimal(PSLICE() << first).move_as_ok(); td::BigNum p = td::BigNum::from_decimal(PSLICE() << first).move_as_ok();
BigNum q = BigNum::from_decimal(PSLICE() << second).move_as_ok(); td::BigNum q = td::BigNum::from_decimal(PSLICE() << second).move_as_ok();
BigNum pq; td::BigNum pq;
BigNumContext context; td::BigNumContext context;
BigNum::mul(pq, p, q, context); td::BigNum::mul(pq, p, q, context);
std::string pq_str = pq.to_binary(); 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); int err = td::pq_factorize(pq_str, &p_str, &q_str);
LOG_CHECK(err == 0) << first << " * " << second; LOG_CHECK(err == 0) << first << " * " << second;
BigNum p_res = BigNum::from_binary(p_str); td::BigNum p_res = td::BigNum::from_binary(p_str);
BigNum q_res = BigNum::from_binary(q_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(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); LOG_CHECK(q_str == q.to_binary()) << td::tag("got", q_res.to_decimal()) << td::tag("expected", second);