Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
982b994332
@ -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)
|
||||
|
||||
|
@ -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
|
||||
//@start_parameter Parameter for the bot start message if the sponsored chat is a chat with a bot @content Content of the message
|
||||
sponsoredMessage id:int32 sponsor_chat_id:int53 start_parameter:string content:MessageContent = SponsoredMessage;
|
||||
//@link An internal link to be opened when the sponsored message is clicked; may be null. If null, the sponsor chat needs to be opened instead @content Content of the message
|
||||
sponsoredMessage id:int32 sponsor_chat_id:int53 link:InternalLinkType content:MessageContent = SponsoredMessage;
|
||||
|
||||
//@description Contains a list of sponsored messages @messages List of sponsored messages
|
||||
sponsoredMessages messages:vector<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
|
||||
personalDetails first_name:string middle_name:string last_name:string native_first_name:string native_middle_name:string native_last_name:string birthdate:date gender:string country_code:string residence_country_code:string = PersonalDetails;
|
||||
|
||||
//@description An identity document @number Document number; 1-24 characters @expiry_date Document expiry date; may be null @front_side Front side of the document
|
||||
//@description An identity document @number Document number; 1-24 characters @expiry_date Document expiry date; may be null if not applicable @front_side Front side of the document
|
||||
//@reverse_side Reverse side of the document; only for driver license and identity card; may be null @selfie Selfie with the document; may be null @translation List of files containing a certified English translation of the document
|
||||
identityDocument number:string expiry_date:date front_side:datedFile reverse_side:datedFile selfie:datedFile translation:vector<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
|
||||
inputIdentityDocument number:string expiry_date:date front_side:InputFile reverse_side:InputFile selfie:InputFile translation:vector<InputFile> = InputIdentityDocument;
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
|
||||
|
||||
if (POLICY CMP0065)
|
||||
# do not export symbols from executables
|
||||
# affects compiler checks in project(), so must be set before it
|
||||
cmake_policy(SET CMP0065 NEW)
|
||||
endif()
|
||||
|
||||
project(tl-parser LANGUAGES C)
|
||||
|
||||
set(SOURCES crc32.h crc32.c tlc.c tl-parser.c tl-parser.h tl-parser-tree.h tl-tl.h portable_endian.h)
|
||||
|
@ -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) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
// TODO invokeAfter and log event
|
||||
auto file_view = td_->file_manager_->get_file_view(animation_id);
|
||||
|
@ -472,9 +472,8 @@ Result<string> BackgroundManager::get_background_url(const string &name,
|
||||
void BackgroundManager::reload_background_from_server(
|
||||
BackgroundId background_id, const string &background_name,
|
||||
telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper, Promise<Unit> &&promise) const {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
td_->create_handler<GetBackgroundQuery>(std::move(promise))
|
||||
->send(background_id, background_name, std::move(input_wallpaper));
|
||||
}
|
||||
|
@ -840,7 +840,7 @@ void CallActor::send_with_promise(NetQueryPtr query, Promise<NetQueryPtr> promis
|
||||
|
||||
void CallActor::hangup() {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -274,9 +274,7 @@ void CallbackQueriesManager::send_get_callback_answer_query(
|
||||
FullMessageId full_message_id, tl_object_ptr<td_api::CallbackQueryPayload> &&payload,
|
||||
tl_object_ptr<telegram_api::InputCheckPasswordSRP> &&password,
|
||||
Promise<td_api::object_ptr<td_api::callbackQueryAnswer>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
||||
|
@ -956,9 +956,7 @@ void ConfigManager::lazy_request_config() {
|
||||
}
|
||||
|
||||
void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
|
||||
if (auth_manager != nullptr && auth_manager->is_bot()) {
|
||||
@ -974,9 +972,7 @@ void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>
|
||||
}
|
||||
|
||||
void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
|
||||
if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) {
|
||||
@ -991,9 +987,7 @@ void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
|
||||
}
|
||||
|
||||
void ConfigManager::set_content_settings(bool ignore_sensitive_content_restrictions, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
last_set_content_settings_ = ignore_sensitive_content_restrictions;
|
||||
auto &queries = set_content_settings_queries_[ignore_sensitive_content_restrictions];
|
||||
@ -1011,9 +1005,7 @@ void ConfigManager::set_content_settings(bool ignore_sensitive_content_restricti
|
||||
}
|
||||
|
||||
void ConfigManager::get_global_privacy_settings(Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
|
||||
if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) {
|
||||
@ -1028,9 +1020,8 @@ void ConfigManager::get_global_privacy_settings(Promise<Unit> &&promise) {
|
||||
}
|
||||
|
||||
void ConfigManager::set_archive_and_mute(bool archive_and_mute, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
if (archive_and_mute) {
|
||||
remove_suggested_action(suggested_actions_, SuggestedAction{SuggestedAction::Type::EnableArchiveAndMuteNewChats});
|
||||
}
|
||||
|
@ -1185,13 +1185,11 @@ class TogglePrehistoryHiddenQuery final : public Td::ResultHandler {
|
||||
|
||||
td->updates_manager_->on_get_updates(
|
||||
std::move(ptr),
|
||||
PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_,
|
||||
PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_),
|
||||
channel_id = channel_id_,
|
||||
is_all_history_available = is_all_history_available_](Unit result) mutable {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_is_all_history_available,
|
||||
channel_id, is_all_history_available, std::move(promise));
|
||||
send_closure(actor_id, &ContactsManager::on_update_channel_is_all_history_available, channel_id,
|
||||
is_all_history_available, std::move(promise));
|
||||
}));
|
||||
}
|
||||
|
||||
@ -1417,13 +1415,11 @@ class ToggleSlowModeQuery final : public Td::ResultHandler {
|
||||
LOG(INFO) << "Receive result for ToggleSlowModeQuery: " << to_string(ptr);
|
||||
|
||||
td->updates_manager_->on_get_updates(
|
||||
std::move(ptr), PromiseCreator::lambda([promise = std::move(promise_), channel_id = channel_id_,
|
||||
slow_mode_delay = slow_mode_delay_](Unit result) mutable {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
send_closure(G()->contacts_manager(), &ContactsManager::on_update_channel_slow_mode_delay, channel_id,
|
||||
slow_mode_delay, std::move(promise));
|
||||
std::move(ptr),
|
||||
PromiseCreator::lambda([actor_id = G()->contacts_manager(), promise = std::move(promise_),
|
||||
channel_id = channel_id_, slow_mode_delay = slow_mode_delay_](Unit result) mutable {
|
||||
send_closure(actor_id, &ContactsManager::on_update_channel_slow_mode_delay, channel_id, slow_mode_delay,
|
||||
std::move(promise));
|
||||
}));
|
||||
}
|
||||
|
||||
@ -5327,9 +5323,7 @@ void ContactsManager::reload_contacts(bool force) {
|
||||
}
|
||||
|
||||
void ContactsManager::add_contact(Contact contact, bool share_phone_number, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
if (!are_contacts_loaded_) {
|
||||
load_contacts(PromiseCreator::lambda([actor_id = actor_id(this), contact = std::move(contact), share_phone_number,
|
||||
@ -5475,11 +5469,12 @@ void ContactsManager::on_load_imported_contacts_from_database(string value) {
|
||||
LOG(INFO) << "Successfully loaded " << all_imported_contacts_.size() << " imported contacts from database";
|
||||
}
|
||||
|
||||
load_imported_contact_users_multipromise_.add_promise(PromiseCreator::lambda([](Result<> result) {
|
||||
if (result.is_ok()) {
|
||||
send_closure_later(G()->contacts_manager(), &ContactsManager::on_load_imported_contacts_finished);
|
||||
}
|
||||
}));
|
||||
load_imported_contact_users_multipromise_.add_promise(
|
||||
PromiseCreator::lambda([actor_id = actor_id(this)](Result<Unit> result) {
|
||||
if (result.is_ok()) {
|
||||
send_closure_later(actor_id, &ContactsManager::on_load_imported_contacts_finished);
|
||||
}
|
||||
}));
|
||||
|
||||
auto lock_promise = load_imported_contact_users_multipromise_.get_promise();
|
||||
|
||||
@ -5729,9 +5724,7 @@ std::pair<int32, vector<UserId>> ContactsManager::search_contacts(const string &
|
||||
}
|
||||
|
||||
void ContactsManager::share_phone_number(UserId user_id, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
if (!are_contacts_loaded_) {
|
||||
load_contacts(PromiseCreator::lambda(
|
||||
@ -6185,7 +6178,8 @@ void ContactsManager::upload_profile_photo(FileId file_id, bool is_animation, do
|
||||
CHECK(uploaded_profile_photos_.find(file_id) == uploaded_profile_photos_.end());
|
||||
uploaded_profile_photos_.emplace(
|
||||
file_id, UploadedProfilePhoto{main_frame_timestamp, is_animation, reupload_count, std::move(promise)});
|
||||
LOG(INFO) << "Ask to upload profile photo " << file_id << " with bad parts " << bad_parts;
|
||||
LOG(INFO) << "Ask to upload " << (is_animation ? "animated" : "static") << " profile photo " << file_id
|
||||
<< " with bad parts " << bad_parts;
|
||||
// TODO use force_reupload if reupload_count >= 1, replace reupload_count with is_reupload
|
||||
td_->file_manager_->resume_upload(file_id, std::move(bad_parts), upload_profile_photo_callback_, 32, 0);
|
||||
}
|
||||
@ -6584,9 +6578,7 @@ void ContactsManager::get_channel_statistics_dc_id(DialogId dialog_id, bool for_
|
||||
|
||||
void ContactsManager::get_channel_statistics_dc_id_impl(ChannelId channel_id, bool for_full_statistics,
|
||||
Promise<DcId> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto channel_full = get_channel_full(channel_id, false, "get_channel_statistics_dc_id_impl");
|
||||
if (channel_full == nullptr) {
|
||||
@ -6615,9 +6607,8 @@ void ContactsManager::get_channel_statistics(DialogId dialog_id, bool is_dark,
|
||||
|
||||
void ContactsManager::send_get_channel_stats_query(DcId dc_id, ChannelId channel_id, bool is_dark,
|
||||
Promise<td_api::object_ptr<td_api::ChatStatistics>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
const Channel *c = get_channel(channel_id);
|
||||
CHECK(c != nullptr);
|
||||
if (c->is_megagroup) {
|
||||
@ -6666,9 +6657,7 @@ void ContactsManager::get_channel_message_statistics(FullMessageId full_message_
|
||||
void ContactsManager::send_get_channel_message_stats_query(
|
||||
DcId dc_id, FullMessageId full_message_id, bool is_dark,
|
||||
Promise<td_api::object_ptr<td_api::messageStatistics>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
if (!td_->messages_manager_->have_message_force(full_message_id, "send_get_channel_message_stats_query")) {
|
||||
@ -6697,9 +6686,7 @@ void ContactsManager::load_statistics_graph(DialogId dialog_id, const string &to
|
||||
|
||||
void ContactsManager::send_load_async_graph_query(DcId dc_id, string token, int64 x,
|
||||
Promise<td_api::object_ptr<td_api::StatisticalGraph>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
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(
|
||||
ChannelId channel_id, UserId user_id, tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
td_->create_handler<EditChannelCreatorQuery>(std::move(promise))
|
||||
->send(channel_id, user_id, std::move(input_check_password));
|
||||
@ -7285,10 +7270,7 @@ void ContactsManager::export_dialog_invite_link(DialogId dialog_id, int32 expire
|
||||
void ContactsManager::export_dialog_invite_link_impl(DialogId dialog_id, int32 expire_date, int32 usage_limit,
|
||||
bool is_permanent,
|
||||
Promise<td_api::object_ptr<td_api::chatInviteLink>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_STATUS_PROMISE(promise, can_manage_dialog_invite_links(dialog_id));
|
||||
|
||||
td_->create_handler<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,
|
||||
DialogParticipantStatus status, DialogParticipantStatus old_status,
|
||||
Promise<Unit> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
LOG(INFO) << "Restrict " << participant_dialog_id << " in " << channel_id << " from " << old_status << " to "
|
||||
<< status;
|
||||
const Channel *c = get_channel(channel_id);
|
||||
@ -7536,22 +7520,22 @@ void ContactsManager::restrict_channel_participant(ChannelId channel_id, DialogI
|
||||
|
||||
if (old_status.is_member() && !status.is_member() && !status.is_banned()) {
|
||||
// we can't make participant Left without kicking it first
|
||||
auto on_result_promise = PromiseCreator::lambda([channel_id, participant_dialog_id, status,
|
||||
promise = std::move(promise)](Result<> result) mutable {
|
||||
auto on_result_promise = PromiseCreator::lambda([actor_id = actor_id(this), channel_id, participant_dialog_id,
|
||||
status, promise = std::move(promise)](Result<> result) mutable {
|
||||
if (result.is_error()) {
|
||||
return promise.set_error(result.move_as_error());
|
||||
}
|
||||
|
||||
create_actor<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 {
|
||||
if (result.is_error()) {
|
||||
return promise.set_error(result.move_as_error());
|
||||
}
|
||||
|
||||
send_closure(G()->contacts_manager(), &ContactsManager::restrict_channel_participant,
|
||||
channel_id, participant_dialog_id, status,
|
||||
DialogParticipantStatus::Banned(0), std::move(promise));
|
||||
send_closure(actor_id, &ContactsManager::restrict_channel_participant, channel_id,
|
||||
participant_dialog_id, status, DialogParticipantStatus::Banned(0),
|
||||
std::move(promise));
|
||||
}))
|
||||
.release();
|
||||
});
|
||||
@ -7969,10 +7953,10 @@ void ContactsManager::on_load_contacts_from_database(string value) {
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << user_ids.size() << " contacts from database";
|
||||
|
||||
load_contact_users_multipromise_.add_promise(
|
||||
PromiseCreator::lambda([expected_contact_count = user_ids.size()](Result<> result) {
|
||||
load_contact_users_multipromise_.add_promise(PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), expected_contact_count = user_ids.size()](Result<Unit> result) {
|
||||
if (result.is_ok()) {
|
||||
send_closure(G()->contacts_manager(), &ContactsManager::on_get_contacts_finished, expected_contact_count);
|
||||
send_closure(actor_id, &ContactsManager::on_get_contacts_finished, expected_contact_count);
|
||||
}
|
||||
}));
|
||||
|
||||
@ -9693,18 +9677,18 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
|
||||
}
|
||||
}
|
||||
if (u->is_name_changed) {
|
||||
td_->messages_manager_->on_dialog_title_updated(DialogId(user_id));
|
||||
for_each_secret_chat_with_user(user_id,
|
||||
[messages_manager = td_->messages_manager_.get()](SecretChatId secret_chat_id) {
|
||||
messages_manager->on_dialog_title_updated(DialogId(secret_chat_id));
|
||||
});
|
||||
auto messages_manager = td_->messages_manager_.get();
|
||||
messages_manager->on_dialog_title_updated(DialogId(user_id));
|
||||
for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) {
|
||||
messages_manager->on_dialog_title_updated(DialogId(secret_chat_id));
|
||||
});
|
||||
}
|
||||
if (u->is_photo_changed) {
|
||||
td_->messages_manager_->on_dialog_photo_updated(DialogId(user_id));
|
||||
for_each_secret_chat_with_user(user_id,
|
||||
[messages_manager = td_->messages_manager_.get()](SecretChatId secret_chat_id) {
|
||||
messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id));
|
||||
});
|
||||
auto messages_manager = td_->messages_manager_.get();
|
||||
messages_manager->on_dialog_photo_updated(DialogId(user_id));
|
||||
for_each_secret_chat_with_user(user_id, [messages_manager](SecretChatId secret_chat_id) {
|
||||
messages_manager->on_dialog_photo_updated(DialogId(secret_chat_id));
|
||||
});
|
||||
}
|
||||
if (u->is_status_changed && user_id != get_my_id()) {
|
||||
auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached();
|
||||
@ -10437,7 +10421,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
||||
if (chat->groupcall_default_join_as_ != nullptr) {
|
||||
default_join_group_call_as_dialog_id = DialogId(chat->groupcall_default_join_as_);
|
||||
}
|
||||
// use send closure later to not crete synchronously default_join_group_call_as_dialog_id
|
||||
// use send closure later to not create synchronously default_join_group_call_as_dialog_id
|
||||
send_closure_later(G()->messages_manager(),
|
||||
&MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(chat_id),
|
||||
default_join_group_call_as_dialog_id, false);
|
||||
@ -10653,7 +10637,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
|
||||
if (channel->groupcall_default_join_as_ != nullptr) {
|
||||
default_join_group_call_as_dialog_id = DialogId(channel->groupcall_default_join_as_);
|
||||
}
|
||||
// use send closure later to not crete synchronously default_join_group_call_as_dialog_id
|
||||
// use send closure later to not create synchronously default_join_group_call_as_dialog_id
|
||||
send_closure_later(G()->messages_manager(),
|
||||
&MessagesManager::on_update_dialog_default_join_group_call_as_dialog_id, DialogId(channel_id),
|
||||
default_join_group_call_as_dialog_id, false);
|
||||
@ -11701,9 +11685,7 @@ void ContactsManager::on_get_channel_participants(
|
||||
ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit, string additional_query,
|
||||
int32 additional_limit, tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
|
||||
Promise<DialogParticipants> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
on_get_users(std::move(channel_participants->users_), "on_get_channel_participants");
|
||||
on_get_chats(std::move(channel_participants->chats_), "on_get_channel_participants");
|
||||
@ -13331,9 +13313,8 @@ void ContactsManager::on_update_channel_location(ChannelId channel_id, const Dia
|
||||
|
||||
void ContactsManager::on_update_channel_slow_mode_delay(ChannelId channel_id, int32 slow_mode_delay,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_slow_mode_delay");
|
||||
if (channel_full != nullptr) {
|
||||
on_update_channel_full_slow_mode_delay(channel_full, channel_id, slow_mode_delay, 0);
|
||||
@ -13380,9 +13361,7 @@ void ContactsManager::on_update_channel_full_bot_user_ids(ChannelFull *channel_f
|
||||
|
||||
void ContactsManager::on_update_channel_is_all_history_available(ChannelId channel_id, bool is_all_history_available,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
CHECK(channel_id.is_valid());
|
||||
auto channel_full = get_channel_full_force(channel_id, true, "on_update_channel_is_all_history_available");
|
||||
if (channel_full != nullptr && channel_full->is_all_history_available != is_all_history_available) {
|
||||
@ -14766,9 +14745,7 @@ void ContactsManager::get_dialog_participant(DialogId dialog_id,
|
||||
|
||||
void ContactsManager::finish_get_dialog_participant(DialogParticipant &&dialog_participant,
|
||||
Promise<td_api::object_ptr<td_api::chatMember>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto participant_dialog_id = dialog_participant.dialog_id;
|
||||
bool is_user = participant_dialog_id.get_type() == DialogType::User;
|
||||
@ -14979,9 +14956,7 @@ void ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, Promi
|
||||
|
||||
void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id,
|
||||
Promise<DialogParticipant> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
const auto *participant = get_chat_participant(chat_id, user_id);
|
||||
if (participant == nullptr) {
|
||||
@ -15012,9 +14987,7 @@ void ContactsManager::search_chat_participants(ChatId chat_id, const string &que
|
||||
void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &query, int32 limit,
|
||||
DialogParticipantsFilter filter,
|
||||
Promise<DialogParticipants> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto chat_full = get_chat_full(chat_id);
|
||||
if (chat_full == nullptr) {
|
||||
@ -15087,9 +15060,7 @@ void ContactsManager::get_channel_participant(ChannelId channel_id, DialogId par
|
||||
|
||||
void ContactsManager::finish_get_channel_participant(ChannelId channel_id, DialogParticipant &&dialog_participant,
|
||||
Promise<DialogParticipant> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
LOG(INFO) << "Receive a member " << dialog_participant.dialog_id << " of a channel " << channel_id;
|
||||
|
||||
@ -15218,8 +15189,9 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo
|
||||
|
||||
MultiPromiseActorSafe load_users_multipromise{"LoadUsersMultiPromiseActor"};
|
||||
load_users_multipromise.add_promise(
|
||||
PromiseCreator::lambda([dialog_id, administrators, promise = std::move(promise)](Result<> result) mutable {
|
||||
send_closure(G()->contacts_manager(), &ContactsManager::on_load_administrator_users_finished, dialog_id,
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, administrators,
|
||||
promise = std::move(promise)](Result<Unit> result) mutable {
|
||||
send_closure(actor_id, &ContactsManager::on_load_administrator_users_finished, dialog_id,
|
||||
std::move(administrators), std::move(result), std::move(promise));
|
||||
}));
|
||||
|
||||
@ -15235,7 +15207,7 @@ void ContactsManager::on_load_dialog_administrators_from_database(DialogId dialo
|
||||
void ContactsManager::on_load_administrator_users_finished(DialogId dialog_id,
|
||||
vector<DialogAdministrator> administrators, Result<> result,
|
||||
Promise<Unit> promise) {
|
||||
if (result.is_ok()) {
|
||||
if (!G()->close_flag() && result.is_ok()) {
|
||||
dialog_administrators_.emplace(dialog_id, std::move(administrators));
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
@ -15761,8 +15733,6 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
|
||||
}
|
||||
|
||||
void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) {
|
||||
LOG(INFO) << "File " << file_id << " has been uploaded";
|
||||
|
||||
auto it = uploaded_profile_photos_.find(file_id);
|
||||
CHECK(it != uploaded_profile_photos_.end());
|
||||
|
||||
@ -15773,6 +15743,8 @@ void ContactsManager::on_upload_profile_photo(FileId file_id, tl_object_ptr<tele
|
||||
|
||||
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);
|
||||
if (file_view.has_remote_location() && input_file == nullptr) {
|
||||
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
|
||||
if (is_animation) {
|
||||
CHECK(file_view.get_type() == FileType::Animation);
|
||||
LOG_CHECK(file_view.main_remote_location().is_common()) << file_view.main_remote_location();
|
||||
} else {
|
||||
CHECK(file_view.get_type() == FileType::Photo);
|
||||
LOG_CHECK(file_view.main_remote_location().is_photo()) << file_view.main_remote_location();
|
||||
}
|
||||
auto file_reference =
|
||||
is_animation ? FileManager::extract_file_reference(file_view.main_remote_location().as_input_document())
|
||||
|
@ -59,7 +59,7 @@ void DelayDispatcher::tear_down() {
|
||||
while (!queue_.empty()) {
|
||||
auto query = std::move(queue_.front());
|
||||
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));
|
||||
}
|
||||
parent_.reset();
|
||||
|
@ -288,8 +288,11 @@ class DialogDbImpl final : public DialogDbSyncInterface {
|
||||
return std::move(notification_groups);
|
||||
}
|
||||
|
||||
Status begin_transaction() final {
|
||||
return db_.begin_transaction();
|
||||
Status begin_read_transaction() final {
|
||||
return db_.begin_read_transaction();
|
||||
}
|
||||
Status begin_write_transaction() final {
|
||||
return db_.begin_write_transaction();
|
||||
}
|
||||
Status commit_transaction() final {
|
||||
return db_.commit_transaction();
|
||||
@ -463,7 +466,7 @@ class DialogDbAsync final : public DialogDbAsyncInterface {
|
||||
if (pending_writes_.empty()) {
|
||||
return;
|
||||
}
|
||||
sync_db_->begin_transaction().ensure();
|
||||
sync_db_->begin_write_transaction().ensure();
|
||||
for (auto &query : pending_writes_) {
|
||||
query.set_value(Unit());
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ class DialogDbSyncInterface {
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -227,28 +227,17 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source
|
||||
auto &node = nodes_[dest.node_id];
|
||||
node.query->active_queries++;
|
||||
|
||||
auto promise = PromiseCreator::lambda([dest, file_source_id, file_reference_manager = G()->file_reference_manager(),
|
||||
file_manager = G()->file_manager()](Result<Unit> result) {
|
||||
if (G()->close_flag()) {
|
||||
VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing";
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_promise = PromiseCreator::lambda([dest, file_source_id, file_reference_manager](Result<Unit> result) {
|
||||
if (G()->close_flag()) {
|
||||
VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing";
|
||||
return;
|
||||
}
|
||||
|
||||
auto promise = PromiseCreator::lambda([dest, file_source_id, actor_id = actor_id(this),
|
||||
file_manager_actor_id = G()->file_manager()](Result<Unit> result) {
|
||||
auto new_promise = PromiseCreator::lambda([dest, file_source_id, actor_id](Result<Unit> result) {
|
||||
Status status;
|
||||
if (result.is_error()) {
|
||||
status = result.move_as_error();
|
||||
}
|
||||
send_closure(file_reference_manager, &FileReferenceManager::on_query_result, dest, file_source_id,
|
||||
std::move(status), 0);
|
||||
send_closure(actor_id, &FileReferenceManager::on_query_result, dest, file_source_id, std::move(status), 0);
|
||||
});
|
||||
|
||||
send_closure(file_manager, &FileManager::on_file_reference_repaired, dest.node_id, file_source_id,
|
||||
send_closure(file_manager_actor_id, &FileManager::on_file_reference_repaired, dest.node_id, file_source_id,
|
||||
std::move(result), std::move(new_promise));
|
||||
});
|
||||
auto index = static_cast<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 FileSourceWebPage &source) {
|
||||
send_closure_later(G()->web_pages_manager(), &WebPagesManager::reload_web_page_by_url, source.url,
|
||||
std::move(promise));
|
||||
PromiseCreator::lambda([promise = std::move(promise)](Result<WebPageId> &&result) mutable {
|
||||
if (result.is_error()) {
|
||||
promise.set_error(result.move_as_error());
|
||||
} else {
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
}));
|
||||
},
|
||||
[&](const FileSourceSavedAnimations &source) {
|
||||
send_closure_later(G()->animations_manager(), &AnimationsManager::repair_saved_animations, std::move(promise));
|
||||
@ -300,6 +295,11 @@ void FileReferenceManager::send_query(Destination dest, FileSourceId file_source
|
||||
|
||||
FileReferenceManager::Destination FileReferenceManager::on_query_result(Destination dest, FileSourceId file_source_id,
|
||||
Status status, int32 sub) {
|
||||
if (G()->close_flag()) {
|
||||
VLOG(file_references) << "Ignore file reference repair from " << file_source_id << " during closing";
|
||||
return dest;
|
||||
}
|
||||
|
||||
VLOG(file_references) << "Receive result of file reference repair query for file " << dest.node_id
|
||||
<< " with generation " << dest.generation << " from " << file_source_id << ": " << status << " "
|
||||
<< sub;
|
||||
|
@ -383,6 +383,10 @@ class Global final : public ActorContext {
|
||||
#endif
|
||||
}
|
||||
|
||||
static Status request_aborted_error() {
|
||||
return Status::Error(500, "Request aborted");
|
||||
}
|
||||
|
||||
void set_close_flag() {
|
||||
close_flag_ = true;
|
||||
}
|
||||
@ -390,6 +394,10 @@ class Global final : public ActorContext {
|
||||
return close_flag_.load();
|
||||
}
|
||||
|
||||
Status close_status() const {
|
||||
return close_flag() ? request_aborted_error() : Status::OK();
|
||||
}
|
||||
|
||||
bool is_expected_error(const Status &error) const {
|
||||
CHECK(error.is_error());
|
||||
if (error.code() == 401) {
|
||||
|
@ -1325,9 +1325,7 @@ void GroupCallManager::create_voice_chat(DialogId dialog_id, string title, int32
|
||||
|
||||
void GroupCallManager::on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id,
|
||||
Promise<GroupCallId> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
if (!input_group_call_id.is_valid()) {
|
||||
return promise.set_error(Status::Error(500, "Receive invalid group call identifier"));
|
||||
}
|
||||
@ -1404,7 +1402,7 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i
|
||||
load_group_call_queries_.erase(it);
|
||||
|
||||
if (G()->close_flag()) {
|
||||
result = Status::Error(500, "Request aborted");
|
||||
result = Global::request_aborted_error();
|
||||
}
|
||||
|
||||
if (result.is_ok()) {
|
||||
@ -2351,10 +2349,7 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id,
|
||||
int32 channel_id,
|
||||
td_api::object_ptr<td_api::GroupCallVideoQuality> quality,
|
||||
Promise<string> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -2441,10 +2436,7 @@ void GroupCallManager::finish_get_group_call_stream_segment(InputGroupCallId inp
|
||||
}
|
||||
|
||||
void GroupCallManager::start_scheduled_group_call(GroupCallId group_call_id, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -2852,10 +2844,7 @@ void GroupCallManager::process_group_call_after_join_requests(InputGroupCallId i
|
||||
}
|
||||
|
||||
void GroupCallManager::set_group_call_title(GroupCallId group_call_id, string title, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -2929,10 +2918,7 @@ void GroupCallManager::on_edit_group_call_title(InputGroupCallId input_group_cal
|
||||
|
||||
void GroupCallManager::toggle_group_call_is_my_video_paused(GroupCallId group_call_id, bool is_my_video_paused,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3017,10 +3003,7 @@ void GroupCallManager::on_toggle_group_call_is_my_video_paused(InputGroupCallId
|
||||
|
||||
void GroupCallManager::toggle_group_call_is_my_video_enabled(GroupCallId group_call_id, bool is_my_video_enabled,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3108,10 +3091,7 @@ void GroupCallManager::on_toggle_group_call_is_my_video_enabled(InputGroupCallId
|
||||
void GroupCallManager::toggle_group_call_is_my_presentation_paused(GroupCallId group_call_id,
|
||||
bool is_my_presentation_paused,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3199,10 +3179,7 @@ void GroupCallManager::on_toggle_group_call_is_my_presentation_paused(InputGroup
|
||||
|
||||
void GroupCallManager::toggle_group_call_start_subscribed(GroupCallId group_call_id, bool start_subscribed,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3286,10 +3263,7 @@ void GroupCallManager::on_toggle_group_call_start_subscription(InputGroupCallId
|
||||
|
||||
void GroupCallManager::toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3376,10 +3350,7 @@ void GroupCallManager::on_toggle_group_call_mute_new_participants(InputGroupCall
|
||||
}
|
||||
|
||||
void GroupCallManager::revoke_group_call_invite_link(GroupCallId group_call_id, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3432,10 +3403,7 @@ void GroupCallManager::invite_group_call_participants(GroupCallId group_call_id,
|
||||
|
||||
void GroupCallManager::get_group_call_invite_link(GroupCallId group_call_id, bool can_self_unmute,
|
||||
Promise<string> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3467,10 +3435,7 @@ void GroupCallManager::get_group_call_invite_link(GroupCallId group_call_id, boo
|
||||
void GroupCallManager::toggle_group_call_recording(GroupCallId group_call_id, bool is_enabled, string title,
|
||||
bool record_video, bool use_portrait_orientation,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3560,10 +3525,7 @@ void GroupCallManager::on_toggle_group_call_recording(InputGroupCallId input_gro
|
||||
|
||||
void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_call_id, int32 audio_source,
|
||||
bool is_speaking, Promise<Unit> &&promise, int32 date) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||
|
||||
auto *group_call = get_group_call(input_group_call_id);
|
||||
@ -3609,9 +3571,6 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_
|
||||
if (!is_recursive) {
|
||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, audio_source, is_speaking,
|
||||
promise = std::move(promise), date](Result<Unit> &&result) mutable {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
if (result.is_error()) {
|
||||
promise.set_value(Unit());
|
||||
} else {
|
||||
|
@ -1787,6 +1787,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
||||
resolve_recent_inline_bots_multipromise_.add_promise(std::move(promise));
|
||||
if (recently_used_bots_loaded_ == 0) {
|
||||
resolve_recent_inline_bots_multipromise_.set_ignore_errors(true);
|
||||
auto lock = resolve_recent_inline_bots_multipromise_.get_promise();
|
||||
if (!G()->parameters().use_chat_info_db) {
|
||||
for (auto &bot_username : bot_usernames) {
|
||||
td_->messages_manager_->search_public_dialog(bot_username, false,
|
||||
@ -1798,6 +1799,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
||||
td_->contacts_manager_->get_user(user_id, 3, resolve_recent_inline_bots_multipromise_.get_promise());
|
||||
}
|
||||
}
|
||||
lock.set_value(Unit());
|
||||
recently_used_bots_loaded_ = 1;
|
||||
}
|
||||
return false;
|
||||
|
@ -1313,7 +1313,7 @@ void LanguagePackManager::save_strings_to_database(SqliteKeyValue *kv, int32 new
|
||||
return;
|
||||
}
|
||||
|
||||
kv->begin_transaction().ensure();
|
||||
kv->begin_write_transaction().ensure();
|
||||
for (auto str : strings) {
|
||||
if (!is_valid_key(str.first)) {
|
||||
LOG(ERROR) << "Have invalid key \"" << str.first << '"';
|
||||
@ -1873,7 +1873,7 @@ void LanguagePackManager::send_with_promise(NetQueryPtr query, Promise<NetQueryP
|
||||
|
||||
void LanguagePackManager::hangup() {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -3987,16 +3987,16 @@ unique_ptr<MessageContent> get_secret_message_content(
|
||||
}
|
||||
auto url = r_http_url.ok().get_url();
|
||||
|
||||
auto web_page_id = td->web_pages_manager_->get_web_page_by_url(url, load_data_multipromise.get_promise());
|
||||
auto result = make_unique<MessageText>(FormattedText{std::move(message_text), std::move(entities)}, web_page_id);
|
||||
if (!result->web_page_id.is_valid()) {
|
||||
load_data_multipromise.add_promise(
|
||||
PromiseCreator::lambda([td, url, &web_page_id = result->web_page_id](Result<Unit> result) {
|
||||
if (result.is_ok()) {
|
||||
web_page_id = td->web_pages_manager_->get_web_page_by_url(url);
|
||||
}
|
||||
}));
|
||||
}
|
||||
auto result = make_unique<MessageText>(FormattedText{std::move(message_text), std::move(entities)}, WebPageId());
|
||||
td->web_pages_manager_->get_web_page_by_url(
|
||||
url,
|
||||
PromiseCreator::lambda([&web_page_id = result->web_page_id, promise = load_data_multipromise.get_promise()](
|
||||
Result<WebPageId> r_web_page_id) mutable {
|
||||
if (r_web_page_id.is_ok()) {
|
||||
web_page_id = r_web_page_id.move_as_ok();
|
||||
}
|
||||
promise.set_value(Unit());
|
||||
}));
|
||||
return std::move(result);
|
||||
}
|
||||
case secret_api::decryptedMessageMediaExternalDocument::ID: {
|
||||
|
@ -809,8 +809,8 @@ class MessagesDbImpl final : public MessagesDbSyncInterface {
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
Status begin_transaction() final {
|
||||
return db_.begin_transaction();
|
||||
Status begin_write_transaction() final {
|
||||
return db_.begin_write_transaction();
|
||||
}
|
||||
Status commit_transaction() final {
|
||||
return db_.commit_transaction();
|
||||
@ -1176,7 +1176,7 @@ class MessagesDbAsync final : public MessagesDbAsyncInterface {
|
||||
if (pending_writes_.empty()) {
|
||||
return;
|
||||
}
|
||||
sync_db_->begin_transaction().ensure();
|
||||
sync_db_->begin_write_transaction().ensure();
|
||||
for (auto &query : pending_writes_) {
|
||||
query.set_value(Unit());
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ class MessagesDbSyncInterface {
|
||||
virtual Result<MessagesDbCallsResult> get_calls(MessagesDbCallsQuery 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;
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -189,7 +189,7 @@ class MessagesManager final : public Actor {
|
||||
int32 total_count = 0;
|
||||
bool is_channel_messages = false;
|
||||
};
|
||||
MessagesInfo on_get_messages(tl_object_ptr<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,
|
||||
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 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,
|
||||
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,
|
||||
MessageSearchFilter filter, MessageId top_thread_message_id,
|
||||
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_get_dialog_message_count(DialogId dialog_id, MessageSearchFilter filter, int32 total_count,
|
||||
@ -220,7 +221,7 @@ class MessagesManager final : public Actor {
|
||||
void on_get_messages_search_result(const string &query, int32 offset_date, DialogId offset_dialog_id,
|
||||
MessageId offset_message_id, int32 limit, MessageSearchFilter filter,
|
||||
int32 min_date, int32 max_date, int64 random_id, int32 total_count,
|
||||
vector<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_get_scheduled_server_messages(DialogId dialog_id, uint32 generation,
|
||||
@ -547,13 +548,11 @@ class MessagesManager final : public Actor {
|
||||
void block_message_sender_from_replies(MessageId message_id, bool delete_message, bool delete_all_messages,
|
||||
bool report_spam, Promise<Unit> &&promise);
|
||||
|
||||
std::pair<int32, vector<DialogId>> get_blocked_dialogs(int32 offset, int32 limit, int64 &random_id,
|
||||
Promise<Unit> &&promise);
|
||||
void get_blocked_dialogs(int32 offset, int32 limit, Promise<td_api::object_ptr<td_api::messageSenders>> &&promise);
|
||||
|
||||
void on_get_blocked_dialogs(int32 offset, int32 limit, int64 random_id, int32 total_count,
|
||||
vector<tl_object_ptr<telegram_api::peerBlocked>> &&blocked_peers);
|
||||
|
||||
void on_failed_get_blocked_dialogs(int64 random_id);
|
||||
void on_get_blocked_dialogs(int32 offset, int32 limit, int32 total_count,
|
||||
vector<tl_object_ptr<telegram_api::peerBlocked>> &&blocked_peers,
|
||||
Promise<td_api::object_ptr<td_api::messageSenders>> &&promise);
|
||||
|
||||
bool can_get_message_statistics(FullMessageId full_message_id);
|
||||
|
||||
@ -728,7 +727,8 @@ class MessagesManager final : public Actor {
|
||||
int64 get_dialog_message_by_date(DialogId dialog_id, int32 date, Promise<Unit> &&promise);
|
||||
|
||||
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);
|
||||
|
||||
@ -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 on_add_secret_message_ready(int64 token);
|
||||
|
||||
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);
|
||||
@ -2133,7 +2135,7 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void load_folder_dialog_list(FolderId folder_id, int32 limit, bool only_local);
|
||||
|
||||
void on_load_folder_dialog_list_fail(FolderId folder_id, Status error);
|
||||
void on_load_folder_dialog_list(FolderId folder_id, Result<Unit> &&result);
|
||||
|
||||
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 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;
|
||||
|
||||
@ -3273,9 +3275,6 @@ class MessagesManager final : public Actor {
|
||||
};
|
||||
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, std::pair<int32, vector<MessageId>>>
|
||||
|
@ -839,7 +839,7 @@ void PasswordManager::start_up() {
|
||||
|
||||
void PasswordManager::hangup() {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -561,7 +561,7 @@ void PrivacyManager::send_with_promise(NetQueryPtr query, Promise<NetQueryPtr> p
|
||||
|
||||
void PrivacyManager::hangup() {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,13 @@ void RecentDialogList::on_load_dialogs(vector<string> &&found_dialogs) {
|
||||
auto promises = std::move(load_list_queries_);
|
||||
CHECK(!promises.empty());
|
||||
|
||||
if (G()->close_flag()) {
|
||||
for (auto &promise : promises) {
|
||||
promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto newly_found_dialogs = std::move(dialog_ids_);
|
||||
reset_to_empty(dialog_ids_);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/AuthManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
|
||||
@ -127,7 +128,7 @@ class RequestActor : public Actor {
|
||||
}
|
||||
|
||||
void hangup() final {
|
||||
do_send_error(Status::Error(500, "Request aborted"));
|
||||
do_send_error(Global::request_aborted_error());
|
||||
stop();
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
decryptedMessageActionResend#511110b0 start_seq_no:int end_seq_no:int = DecryptedMessageAction;
|
||||
decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
|
||||
decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction;
|
||||
decryptedMessageActionRequestKey#f3c9611b exchange_id:long g_a:bytes = DecryptedMessageAction;
|
||||
decryptedMessageActionAcceptKey#6fe1735b exchange_id:long g_b:bytes key_fingerprint:long = DecryptedMessageAction;
|
||||
decryptedMessageActionAbortKey#dd05ec6b exchange_id:long = DecryptedMessageAction;
|
||||
decryptedMessageActionCommitKey#ec2e0b9b exchange_id:long key_fingerprint:long = DecryptedMessageAction;
|
||||
decryptedMessageActionNoop#a82fdd63 = DecryptedMessageAction;
|
||||
*/
|
||||
save_message_finish.set_value(Unit());
|
||||
break;
|
||||
}
|
||||
@ -1379,7 +1369,7 @@ void SecretChatActor::on_save_changes_start(ChangesProcessor<StateChange>::Id sa
|
||||
}
|
||||
|
||||
void SecretChatActor::on_inbound_save_message_finish(uint64 state_id) {
|
||||
if (close_flag_) {
|
||||
if (close_flag_ || context_->close_flag()) {
|
||||
return;
|
||||
}
|
||||
auto *state = inbound_message_states_.get(state_id);
|
||||
|
@ -582,7 +582,7 @@ void SetSecureValue::loop() {
|
||||
}
|
||||
|
||||
void SetSecureValue::hangup() {
|
||||
on_error(Status::Error(406, "Request aborted"));
|
||||
on_error(Status::Error(406, "Request canceled"));
|
||||
}
|
||||
|
||||
void SetSecureValue::tear_down() {
|
||||
@ -1294,7 +1294,7 @@ void SecureManager::get_preferred_country_language(string country_code,
|
||||
|
||||
void SecureManager::hangup() {
|
||||
container_.for_each(
|
||||
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Status::Error(500, "Request aborted")); });
|
||||
[](auto id, Promise<NetQueryPtr> &promise) { promise.set_error(Global::request_aborted_error()); });
|
||||
dec_refcnt();
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ void SequenceDispatcher::tear_down() {
|
||||
continue;
|
||||
}
|
||||
data.state_ = State::Dummy;
|
||||
data.query_->set_error(Status::Error(500, "Request aborted"));
|
||||
data.query_->set_error(Global::request_aborted_error());
|
||||
do_finish(data);
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
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>(
|
||||
sponsored_message.local_id, sponsored_message.sponsor_dialog_id.get(), sponsored_message.start_param,
|
||||
sponsored_message.local_id, sponsored_message.sponsor_dialog_id.get(), std::move(link),
|
||||
get_message_content_object(sponsored_message.content.get(), td_, dialog_id, 0, false, true, -1));
|
||||
}
|
||||
|
||||
@ -201,7 +218,7 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages(
|
||||
CHECK(messages->message_random_ids.empty());
|
||||
|
||||
if (result.is_ok() && G()->close_flag()) {
|
||||
result = Status::Error(500, "Request aborted");
|
||||
result = Global::request_aborted_error();
|
||||
}
|
||||
if (result.is_error()) {
|
||||
dialog_sponsored_messages_.erase(dialog_id);
|
||||
|
@ -2293,11 +2293,12 @@ StickerSetId StickersManager::on_get_input_sticker_set(FileId sticker_file_id,
|
||||
}
|
||||
auto set_id = search_sticker_set(set->short_name_, load_data_multipromise_ptr->get_promise());
|
||||
if (!set_id.is_valid()) {
|
||||
load_data_multipromise_ptr->add_promise(
|
||||
PromiseCreator::lambda([td = td_, sticker_file_id, short_name = set->short_name_](Result<Unit> result) {
|
||||
load_data_multipromise_ptr->add_promise(PromiseCreator::lambda(
|
||||
[actor_id = actor_id(this), sticker_file_id, short_name = set->short_name_](Result<Unit> result) {
|
||||
if (result.is_ok()) {
|
||||
// just in case
|
||||
td->stickers_manager_->on_resolve_sticker_set_short_name(sticker_file_id, short_name);
|
||||
send_closure(actor_id, &StickersManager::on_resolve_sticker_set_short_name, sticker_file_id,
|
||||
short_name);
|
||||
}
|
||||
}));
|
||||
}
|
||||
@ -2317,6 +2318,10 @@ StickerSetId StickersManager::on_get_input_sticker_set(FileId sticker_file_id,
|
||||
}
|
||||
|
||||
void StickersManager::on_resolve_sticker_set_short_name(FileId sticker_file_id, const string &short_name) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Resolve sticker " << sticker_file_id << " set to " << short_name;
|
||||
StickerSetId set_id = search_sticker_set(short_name, Auto());
|
||||
if (set_id.is_valid()) {
|
||||
@ -3841,9 +3846,7 @@ void StickersManager::reload_sticker_set(StickerSetId sticker_set_id, int64 acce
|
||||
void StickersManager::do_reload_sticker_set(StickerSetId sticker_set_id,
|
||||
tl_object_ptr<telegram_api::InputStickerSet> &&input_sticker_set,
|
||||
Promise<Unit> &&promise) const {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
td_->create_handler<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) {
|
||||
if (!td::contains(dice_emojis_, emoji)) {
|
||||
auto &special_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_dice(emoji));
|
||||
CHECK(!special_sticker_set.id_.is_valid());
|
||||
if (special_sticker_set.id_.is_valid()) {
|
||||
// drop information about the sticker set to reload it
|
||||
special_sticker_set.id_ = StickerSetId();
|
||||
special_sticker_set.access_hash_ = 0;
|
||||
special_sticker_set.short_name_.clear();
|
||||
}
|
||||
|
||||
if (G()->parameters().use_file_db) {
|
||||
LOG(INFO) << "Load new dice sticker set for emoji " << emoji;
|
||||
@ -4149,9 +4157,7 @@ void StickersManager::choose_animated_emoji_click_sticker(const StickerSet *stic
|
||||
|
||||
void StickersManager::send_click_animated_emoji_message_response(
|
||||
FileId sticker_id, Promise<td_api::object_ptr<td_api::sticker>> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
promise.set_value(get_sticker_object(sticker_id));
|
||||
}
|
||||
|
||||
@ -5308,9 +5314,8 @@ void StickersManager::create_new_sticker_set(UserId user_id, string &title, stri
|
||||
} while (random_id == 0 || pending_new_sticker_sets_.find(random_id) != pending_new_sticker_sets_.end());
|
||||
pending_new_sticker_sets_[random_id] = std::move(pending_new_sticker_set);
|
||||
|
||||
multipromise.add_promise(PromiseCreator::lambda([random_id](Result<Unit> result) {
|
||||
send_closure_later(G()->stickers_manager(), &StickersManager::on_new_stickers_uploaded, random_id,
|
||||
std::move(result));
|
||||
multipromise.add_promise(PromiseCreator::lambda([actor_id = actor_id(this), random_id](Result<Unit> result) {
|
||||
send_closure_later(actor_id, &StickersManager::on_new_stickers_uploaded, random_id, std::move(result));
|
||||
}));
|
||||
auto lock_promise = multipromise.get_promise();
|
||||
|
||||
@ -5448,6 +5453,9 @@ void StickersManager::on_new_stickers_uploaded(int64 random_id, Result<Unit> res
|
||||
|
||||
pending_new_sticker_sets_.erase(it);
|
||||
|
||||
if (G()->close_flag()) {
|
||||
result = Global::request_aborted_error();
|
||||
}
|
||||
if (result.is_error()) {
|
||||
pending_new_sticker_set->promise.set_error(result.move_as_error());
|
||||
return;
|
||||
@ -5584,9 +5592,7 @@ void StickersManager::set_sticker_set_thumbnail(UserId user_id, string &short_na
|
||||
void StickersManager::do_set_sticker_set_thumbnail(UserId user_id, string short_name,
|
||||
tl_object_ptr<td_api::InputFile> &&thumbnail,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto it = short_name_to_sticker_set_id_.find(short_name);
|
||||
const StickerSet *sticker_set = it == short_name_to_sticker_set_id_.end() ? nullptr : get_sticker_set(it->second);
|
||||
@ -6009,9 +6015,7 @@ void StickersManager::add_recent_sticker(bool is_attached, const tl_object_ptr<t
|
||||
|
||||
void StickersManager::send_save_recent_sticker_query(bool is_attached, FileId sticker_id, bool unsave,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
// TODO invokeAfter and log event
|
||||
auto file_view = td_->file_manager_->get_file_view(sticker_id);
|
||||
@ -6404,9 +6408,7 @@ void StickersManager::add_favorite_sticker(const tl_object_ptr<td_api::InputFile
|
||||
}
|
||||
|
||||
void StickersManager::send_fave_sticker_query(FileId sticker_id, bool unsave, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
// TODO invokeAfter and log event
|
||||
auto file_view = td_->file_manager_->get_file_view(sticker_id);
|
||||
@ -6806,8 +6808,8 @@ void StickersManager::on_get_emoji_keywords(
|
||||
const string &language_code, Result<telegram_api::object_ptr<telegram_api::emojiKeywordsDifference>> &&result) {
|
||||
auto it = load_emoji_keywords_queries_.find(language_code);
|
||||
CHECK(it != load_emoji_keywords_queries_.end());
|
||||
CHECK(!it->second.empty());
|
||||
auto promises = std::move(it->second);
|
||||
CHECK(!promises.empty());
|
||||
load_emoji_keywords_queries_.erase(it);
|
||||
|
||||
if (result.is_error()) {
|
||||
@ -6919,8 +6921,7 @@ void StickersManager::on_get_emoji_keywords_difference(
|
||||
}
|
||||
version = keywords->version_;
|
||||
auto *pmc = G()->td_db()->get_sqlite_sync_pmc();
|
||||
pmc->begin_transaction().ensure();
|
||||
// set must be the first operation to start a write transaction
|
||||
pmc->begin_write_transaction().ensure();
|
||||
pmc->set(get_emoji_language_code_version_database_key(language_code), to_string(version));
|
||||
pmc->set(get_emoji_language_code_last_difference_time_database_key(language_code), to_string(G()->unix_time()));
|
||||
for (auto &keyword_ptr : keywords->keywords_) {
|
||||
|
@ -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) {
|
||||
if (is_closed_) {
|
||||
promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return;
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
if (pending_storage_stats_.size() != 0) {
|
||||
if (stats_dialog_limit_ == dialog_limit && need_all_files == stats_need_all_files_) {
|
||||
@ -111,7 +110,7 @@ void StorageManager::update_use_storage_optimizer() {
|
||||
void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_file_statistics,
|
||||
Promise<FileStats> promise) {
|
||||
if (is_closed_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
if (!pending_run_gc_[0].empty() || !pending_run_gc_[1].empty()) {
|
||||
close_gc_worker();
|
||||
@ -126,7 +125,7 @@ void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_fil
|
||||
std::move(file_stats));
|
||||
}));
|
||||
|
||||
//NB: get_storage_stats will cancel all gc queries, so promise needs to be added after the call
|
||||
//NB: get_storage_stats will cancel all garbage collection queries, so promise needs to be added after the call
|
||||
pending_run_gc_[return_deleted_file_statistics].push_back(std::move(promise));
|
||||
}
|
||||
|
||||
@ -158,7 +157,7 @@ void StorageManager::create_stats_worker() {
|
||||
void StorageManager::on_all_files(FileGcParameters gc_parameters, Result<FileStats> r_file_stats) {
|
||||
int32 dialog_limit = gc_parameters.dialog_limit;
|
||||
if (is_closed_ && r_file_stats.is_ok()) {
|
||||
r_file_stats = Status::Error(500, "Request aborted");
|
||||
r_file_stats = Global::request_aborted_error();
|
||||
}
|
||||
if (r_file_stats.is_error()) {
|
||||
return on_gc_finished(dialog_limit, r_file_stats.move_as_error());
|
||||
@ -291,7 +290,7 @@ void StorageManager::close_stats_worker() {
|
||||
auto promises = std::move(pending_storage_stats_);
|
||||
pending_storage_stats_.clear();
|
||||
for (auto &promise : promises) {
|
||||
promise.set_error(Status::Error(500, "Request aborted"));
|
||||
promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
stats_generation_++;
|
||||
stats_worker_.reset();
|
||||
@ -304,7 +303,7 @@ void StorageManager::close_gc_worker() {
|
||||
pending_run_gc_[0].clear();
|
||||
pending_run_gc_[1].clear();
|
||||
for (auto &promise : promises) {
|
||||
promise.set_error(Status::Error(500, "Request aborted"));
|
||||
promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
gc_worker_.reset();
|
||||
gc_cancellation_token_source_.cancel();
|
||||
@ -332,7 +331,7 @@ void StorageManager::schedule_next_gc() {
|
||||
!G()->parameters().enable_storage_optimizer) {
|
||||
next_gc_at_ = 0;
|
||||
cancel_timeout();
|
||||
LOG(INFO) << "No next file gc is scheduled";
|
||||
LOG(INFO) << "No next file clean up is scheduled";
|
||||
return;
|
||||
}
|
||||
auto sys_time = static_cast<uint32>(Clocks::system());
|
||||
@ -348,7 +347,7 @@ void StorageManager::schedule_next_gc() {
|
||||
CHECK(next_gc_at >= sys_time);
|
||||
auto next_gc_in = next_gc_at - sys_time;
|
||||
|
||||
LOG(INFO) << "Schedule next file gc in " << next_gc_in;
|
||||
LOG(INFO) << "Schedule next file clean up in " << next_gc_in;
|
||||
next_gc_at_ = Time::now() + next_gc_in;
|
||||
set_timeout_at(next_gc_at_);
|
||||
}
|
||||
@ -364,7 +363,7 @@ void StorageManager::timeout_expired() {
|
||||
next_gc_at_ = 0;
|
||||
run_gc({}, false, PromiseCreator::lambda([actor_id = actor_id(this)](Result<FileStats> r_stats) {
|
||||
if (!r_stats.is_error() || r_stats.error().code() != 500) {
|
||||
// do not save gc timestamp if request was canceled
|
||||
// do not save garbage collection timestamp if request was canceled
|
||||
send_closure(actor_id, &StorageManager::save_last_gc_timestamp);
|
||||
}
|
||||
send_closure(actor_id, &StorageManager::schedule_next_gc);
|
||||
|
@ -1596,15 +1596,22 @@ class GetWebPagePreviewRequest final : public RequestOnceActor {
|
||||
}
|
||||
};
|
||||
|
||||
class GetWebPageInstantViewRequest final : public RequestActor<> {
|
||||
class GetWebPageInstantViewRequest final : public RequestActor<WebPageId> {
|
||||
string url_;
|
||||
bool force_full_;
|
||||
|
||||
WebPageId web_page_id_;
|
||||
|
||||
void do_run(Promise<Unit> &&promise) final {
|
||||
web_page_id_ =
|
||||
td->web_pages_manager_->get_web_page_instant_view(url_, force_full_, get_tries() < 3, std::move(promise));
|
||||
void do_run(Promise<WebPageId> &&promise) final {
|
||||
if (get_tries() < 2) {
|
||||
promise.set_value(std::move(web_page_id_));
|
||||
return;
|
||||
}
|
||||
td->web_pages_manager_->get_web_page_instant_view(url_, force_full_, std::move(promise));
|
||||
}
|
||||
|
||||
void do_set_result(WebPageId &&result) final {
|
||||
web_page_id_ = result;
|
||||
}
|
||||
|
||||
void do_send_result() final {
|
||||
@ -1614,7 +1621,6 @@ class GetWebPageInstantViewRequest final : public RequestActor<> {
|
||||
public:
|
||||
GetWebPageInstantViewRequest(ActorShared<Td> td, uint64 request_id, string url, bool force_full)
|
||||
: RequestActor(std::move(td), request_id), url_(std::move(url)), force_full_(force_full) {
|
||||
set_tries(3);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1856,31 +1862,6 @@ class GetChatEventLogRequest final : public RequestOnceActor {
|
||||
}
|
||||
};
|
||||
|
||||
class GetBlockedMessageSendersRequest final : public RequestActor<> {
|
||||
int32 offset_;
|
||||
int32 limit_;
|
||||
int64 random_id_;
|
||||
|
||||
std::pair<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<> {
|
||||
vector<Contact> contacts_;
|
||||
int64 random_id_;
|
||||
@ -6633,7 +6614,8 @@ void Td::on_request(uint64 id, const td_api::blockMessageSenderFromReplies &requ
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getBlockedMessageSenders &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST(GetBlockedMessageSendersRequest, request.offset_, request.limit_);
|
||||
CREATE_REQUEST_PROMISE();
|
||||
messages_manager_->get_blocked_dialogs(request.offset_, request.limit_, std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::addContact &request) {
|
||||
|
@ -277,6 +277,8 @@ void TdDb::do_close(Promise<> on_finished, bool destroy_flag) {
|
||||
}
|
||||
binlog_.reset();
|
||||
}
|
||||
|
||||
lock.set_value(Unit());
|
||||
}
|
||||
|
||||
Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, DbKey key, DbKey old_key,
|
||||
|
@ -1656,7 +1656,9 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
for (auto &update : updates) {
|
||||
@ -1775,6 +1777,10 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
|
||||
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,
|
||||
Promise<Unit> &&promise) {
|
||||
CHECK(update != nullptr);
|
||||
|
@ -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,
|
||||
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,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
|
@ -94,12 +94,12 @@ class GetWebPagePreviewQuery final : public Td::ResultHandler {
|
||||
};
|
||||
|
||||
class GetWebPageQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
Promise<WebPageId> promise_;
|
||||
WebPageId web_page_id_;
|
||||
string url_;
|
||||
|
||||
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) {
|
||||
@ -123,15 +123,15 @@ class GetWebPageQuery final : public Td::ResultHandler {
|
||||
? web_page->cached_page_views_
|
||||
: 0;
|
||||
td->web_pages_manager_->on_get_web_page_instant_view_view_count(web_page_id_, view_count);
|
||||
return promise_.set_value(std::move(web_page_id_));
|
||||
} else {
|
||||
LOG(ERROR) << "Receive webPageNotModified for " << url_;
|
||||
return on_error(id, Status::Error(500, "Receive webPageNotModified"));
|
||||
}
|
||||
} else {
|
||||
auto web_page_id = td->web_pages_manager_->on_get_web_page(std::move(ptr), DialogId());
|
||||
td->web_pages_manager_->on_get_web_page_by_url(url_, web_page_id, false);
|
||||
}
|
||||
|
||||
promise_.set_value(Unit());
|
||||
auto web_page_id = td->web_pages_manager_->on_get_web_page(std::move(ptr), DialogId());
|
||||
td->web_pages_manager_->on_get_web_page_by_url(url_, web_page_id, false);
|
||||
promise_.set_value(std::move(web_page_id));
|
||||
}
|
||||
|
||||
void on_error(uint64 id, Status status) final {
|
||||
@ -832,50 +832,44 @@ tl_object_ptr<td_api::webPage> WebPagesManager::get_web_page_preview_result(int6
|
||||
return get_web_page_object(web_page_id);
|
||||
}
|
||||
|
||||
WebPageId WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, bool force,
|
||||
Promise<Unit> &&promise) {
|
||||
void WebPagesManager::get_web_page_instant_view(const string &url, bool force_full, Promise<WebPageId> &&promise) {
|
||||
LOG(INFO) << "Trying to get web page instant view for the url \"" << url << '"';
|
||||
auto it = url_to_web_page_id_.find(url);
|
||||
if (it != url_to_web_page_id_.end()) {
|
||||
if (it->second == WebPageId() && !force) {
|
||||
if (it->second == WebPageId()) {
|
||||
// ignore negative caching
|
||||
reload_web_page_by_url(url, std::move(promise));
|
||||
return WebPageId();
|
||||
return reload_web_page_by_url(url, std::move(promise));
|
||||
}
|
||||
return get_web_page_instant_view(it->second, force_full, std::move(promise));
|
||||
}
|
||||
|
||||
load_web_page_by_url(url, std::move(promise));
|
||||
return WebPageId();
|
||||
}
|
||||
|
||||
WebPageId WebPagesManager::get_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<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;
|
||||
|
||||
const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(web_page_id);
|
||||
if (web_page_instant_view == nullptr) {
|
||||
promise.set_value(Unit());
|
||||
return WebPageId();
|
||||
return promise.set_value(WebPageId());
|
||||
}
|
||||
|
||||
if (!web_page_instant_view->is_loaded || (force_full && !web_page_instant_view->is_full)) {
|
||||
load_web_page_instant_view(web_page_id, force_full, std::move(promise));
|
||||
return WebPageId();
|
||||
return load_web_page_instant_view(web_page_id, force_full, std::move(promise));
|
||||
}
|
||||
|
||||
if (force_full) {
|
||||
reload_web_page_instant_view(web_page_id);
|
||||
}
|
||||
|
||||
promise.set_value(Unit());
|
||||
return web_page_id;
|
||||
promise.set_value(std::move(web_page_id));
|
||||
}
|
||||
|
||||
string WebPagesManager::get_web_page_instant_view_database_key(WebPageId web_page_id) {
|
||||
return PSTRING() << "wpiv" << web_page_id.get();
|
||||
}
|
||||
|
||||
void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<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 previous_queries =
|
||||
load_web_page_instant_view_queries.partial.size() + load_web_page_instant_view_queries.full.size();
|
||||
@ -892,9 +886,10 @@ void WebPagesManager::load_web_page_instant_view(WebPageId web_page_id, bool for
|
||||
if (G()->parameters().use_message_db && !web_page_instant_view->was_loaded_from_database) {
|
||||
LOG(INFO) << "Trying to load " << web_page_id << " instant view from database";
|
||||
G()->td_db()->get_sqlite_pmc()->get(
|
||||
get_web_page_instant_view_database_key(web_page_id), PromiseCreator::lambda([web_page_id](string value) {
|
||||
send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_instant_view_from_database,
|
||||
web_page_id, std::move(value));
|
||||
get_web_page_instant_view_database_key(web_page_id),
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](string value) {
|
||||
send_closure(actor_id, &WebPagesManager::on_load_web_page_instant_view_from_database, web_page_id,
|
||||
std::move(value));
|
||||
}));
|
||||
} else {
|
||||
reload_web_page_instant_view(web_page_id);
|
||||
@ -907,14 +902,12 @@ void WebPagesManager::reload_web_page_instant_view(WebPageId web_page_id) {
|
||||
const WebPage *web_page = get_web_page(web_page_id);
|
||||
CHECK(web_page != nullptr && !web_page->instant_view.is_empty);
|
||||
|
||||
auto promise = PromiseCreator::lambda([web_page_id](Result<> result) {
|
||||
send_closure(G()->web_pages_manager(), &WebPagesManager::update_web_page_instant_view_load_requests, web_page_id,
|
||||
true, std::move(result));
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](Result<WebPageId> result) {
|
||||
send_closure(actor_id, &WebPagesManager::update_web_page_instant_view_load_requests, web_page_id, true,
|
||||
std::move(result));
|
||||
});
|
||||
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
td_->create_handler<GetWebPageQuery>(std::move(promise))
|
||||
->send(web_page_id, web_page->url, web_page->instant_view.is_full ? web_page->instant_view.hash : 0);
|
||||
@ -927,7 +920,7 @@ void WebPagesManager::on_load_web_page_instant_view_from_database(WebPageId web_
|
||||
CHECK(G()->parameters().use_message_db);
|
||||
LOG(INFO) << "Successfully loaded " << web_page_id << " instant view of size " << value.size() << " from database";
|
||||
// G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto());
|
||||
// return;
|
||||
// value.clear();
|
||||
|
||||
auto web_page_it = web_pages_.find(web_page_id);
|
||||
if (web_page_it == web_pages_.end() || web_page_it->second->instant_view.is_empty) {
|
||||
@ -936,7 +929,7 @@ void WebPagesManager::on_load_web_page_instant_view_from_database(WebPageId web_
|
||||
if (!value.empty()) {
|
||||
G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto());
|
||||
}
|
||||
update_web_page_instant_view_load_requests(web_page_id, true, Unit());
|
||||
update_web_page_instant_view_load_requests(web_page_id, true, web_page_id);
|
||||
return;
|
||||
}
|
||||
WebPage *web_page = web_page_it->second.get();
|
||||
@ -966,41 +959,42 @@ void WebPagesManager::on_load_web_page_instant_view_from_database(WebPageId web_
|
||||
td_->file_manager_->change_files_source(get_web_page_file_source_id(web_page), old_file_ids, new_file_ids);
|
||||
}
|
||||
|
||||
update_web_page_instant_view_load_requests(web_page_id, false, Unit());
|
||||
update_web_page_instant_view_load_requests(web_page_id, false, web_page_id);
|
||||
}
|
||||
|
||||
void WebPagesManager::update_web_page_instant_view_load_requests(WebPageId web_page_id, bool force_update,
|
||||
Result<> result) {
|
||||
if (G()->close_flag() && result.is_error()) {
|
||||
result = Status::Error(500, "Request aborted");
|
||||
Result<WebPageId> r_web_page_id) {
|
||||
if (G()->close_flag()) {
|
||||
r_web_page_id = Global::request_aborted_error();
|
||||
}
|
||||
LOG(INFO) << "Update load requests for " << web_page_id;
|
||||
auto it = load_web_page_instant_view_queries_.find(web_page_id);
|
||||
if (it == load_web_page_instant_view_queries_.end()) {
|
||||
return;
|
||||
}
|
||||
vector<Promise<Unit>> promises[2];
|
||||
vector<Promise<WebPageId>> promises[2];
|
||||
promises[0] = std::move(it->second.partial);
|
||||
promises[1] = std::move(it->second.full);
|
||||
reset_to_empty(it->second.partial);
|
||||
reset_to_empty(it->second.full);
|
||||
load_web_page_instant_view_queries_.erase(it);
|
||||
|
||||
if (result.is_error()) {
|
||||
LOG(INFO) << "Receive error " << result.error() << " for load " << web_page_id;
|
||||
if (r_web_page_id.is_error()) {
|
||||
LOG(INFO) << "Receive error " << r_web_page_id.error() << " for load " << web_page_id;
|
||||
combine(promises[0], std::move(promises[1]));
|
||||
for (auto &promise : promises[0]) {
|
||||
promise.set_error(result.error().clone());
|
||||
promise.set_error(r_web_page_id.error().clone());
|
||||
}
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Successfully loaded web page " << web_page_id;
|
||||
|
||||
const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(web_page_id);
|
||||
auto new_web_page_id = r_web_page_id.move_as_ok();
|
||||
LOG(INFO) << "Successfully loaded web page " << web_page_id << " as " << new_web_page_id;
|
||||
const WebPageInstantView *web_page_instant_view = get_web_page_instant_view(new_web_page_id);
|
||||
if (web_page_instant_view == nullptr) {
|
||||
combine(promises[0], std::move(promises[1]));
|
||||
for (auto &promise : promises[0]) {
|
||||
promise.set_value(Unit());
|
||||
promise.set_value(WebPageId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1010,26 +1004,27 @@ void WebPagesManager::update_web_page_instant_view_load_requests(WebPageId web_p
|
||||
}
|
||||
|
||||
for (auto &promise : promises[0]) {
|
||||
promise.set_value(Unit());
|
||||
promise.set_value(WebPageId(new_web_page_id));
|
||||
}
|
||||
reset_to_empty(promises[0]);
|
||||
}
|
||||
if (!promises[0].empty() || !promises[1].empty()) {
|
||||
if (force_update) {
|
||||
// protection from cycles
|
||||
LOG(ERROR) << "Expected to receive " << web_page_id << " from the server, but didn't receive it";
|
||||
LOG(ERROR) << "Expected to receive " << web_page_id << '/' << new_web_page_id
|
||||
<< " from the server, but didn't receive it";
|
||||
combine(promises[0], std::move(promises[1]));
|
||||
for (auto &promise : promises[0]) {
|
||||
promise.set_value(Unit());
|
||||
promise.set_value(WebPageId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto &load_queries = load_web_page_instant_view_queries_[web_page_id];
|
||||
auto &load_queries = load_web_page_instant_view_queries_[new_web_page_id];
|
||||
auto old_size = load_queries.partial.size() + load_queries.full.size();
|
||||
combine(load_queries.partial, std::move(promises[0]));
|
||||
combine(load_queries.full, std::move(promises[1]));
|
||||
if (old_size == 0) {
|
||||
reload_web_page_instant_view(web_page_id);
|
||||
reload_web_page_instant_view(new_web_page_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1049,48 +1044,42 @@ WebPageId WebPagesManager::get_web_page_by_url(const string &url) const {
|
||||
return WebPageId();
|
||||
}
|
||||
|
||||
WebPageId WebPagesManager::get_web_page_by_url(const string &url, Promise<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 << '"';
|
||||
|
||||
auto it = url_to_web_page_id_.find(url);
|
||||
if (it != url_to_web_page_id_.end()) {
|
||||
promise.set_value(Unit());
|
||||
return it->second;
|
||||
return promise.set_value(WebPageId(it->second));
|
||||
}
|
||||
|
||||
load_web_page_by_url(url, std::move(promise));
|
||||
return WebPageId();
|
||||
}
|
||||
|
||||
void WebPagesManager::load_web_page_by_url(const string &url, Promise<Unit> &&promise) {
|
||||
void WebPagesManager::load_web_page_by_url(const string &url, Promise<WebPageId> &&promise) {
|
||||
if (!G()->parameters().use_message_db) {
|
||||
reload_web_page_by_url(url, std::move(promise));
|
||||
return;
|
||||
return reload_web_page_by_url(url, std::move(promise));
|
||||
}
|
||||
|
||||
LOG(INFO) << "Load \"" << url << '"';
|
||||
G()->td_db()->get_sqlite_pmc()->get(get_web_page_url_database_key(url),
|
||||
PromiseCreator::lambda([url, promise = std::move(promise)](string value) mutable {
|
||||
send_closure(G()->web_pages_manager(),
|
||||
&WebPagesManager::on_load_web_page_id_by_url_from_database, url,
|
||||
value, std::move(promise));
|
||||
}));
|
||||
G()->td_db()->get_sqlite_pmc()->get(
|
||||
get_web_page_url_database_key(url),
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), url, promise = std::move(promise)](string value) mutable {
|
||||
send_closure(actor_id, &WebPagesManager::on_load_web_page_id_by_url_from_database, std::move(url),
|
||||
std::move(value), std::move(promise));
|
||||
}));
|
||||
}
|
||||
|
||||
void WebPagesManager::on_load_web_page_id_by_url_from_database(const string &url, string value,
|
||||
Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
void WebPagesManager::on_load_web_page_id_by_url_from_database(string url, string value, Promise<WebPageId> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
LOG(INFO) << "Successfully loaded url \"" << url << "\" of size " << value.size() << " from database";
|
||||
// G()->td_db()->get_sqlite_pmc()->erase(get_web_page_url_database_key(web_page_id), Auto());
|
||||
// return;
|
||||
// value.clear();
|
||||
|
||||
auto it = url_to_web_page_id_.find(url);
|
||||
if (it != url_to_web_page_id_.end()) {
|
||||
// URL web page has already been loaded
|
||||
promise.set_value(Unit());
|
||||
return;
|
||||
return promise.set_value(WebPageId(it->second));
|
||||
}
|
||||
if (!value.empty()) {
|
||||
auto web_page_id = WebPageId(to_integer<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)) {
|
||||
// URL web page has already been loaded
|
||||
on_get_web_page_by_url(url, web_page_id, true);
|
||||
promise.set_value(Unit());
|
||||
promise.set_value(WebPageId(web_page_id));
|
||||
return;
|
||||
}
|
||||
|
||||
load_web_page_from_database(
|
||||
web_page_id,
|
||||
PromiseCreator::lambda([web_page_id, url, promise = std::move(promise)](Result<> result) mutable {
|
||||
send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_by_url_from_database, web_page_id,
|
||||
url, std::move(promise), std::move(result));
|
||||
}));
|
||||
load_web_page_from_database(web_page_id,
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), web_page_id, url = std::move(url),
|
||||
promise = std::move(promise)](Result<Unit> result) mutable {
|
||||
send_closure(actor_id, &WebPagesManager::on_load_web_page_by_url_from_database,
|
||||
web_page_id, std::move(url), std::move(promise), std::move(result));
|
||||
}));
|
||||
return;
|
||||
} else {
|
||||
LOG(ERROR) << "Receive invalid " << web_page_id;
|
||||
@ -1117,33 +1106,27 @@ void WebPagesManager::on_load_web_page_id_by_url_from_database(const string &url
|
||||
reload_web_page_by_url(url, std::move(promise));
|
||||
}
|
||||
|
||||
void WebPagesManager::on_load_web_page_by_url_from_database(WebPageId web_page_id, const string &url,
|
||||
Promise<Unit> &&promise, Result<> result) {
|
||||
void WebPagesManager::on_load_web_page_by_url_from_database(WebPageId web_page_id, string url,
|
||||
Promise<WebPageId> &&promise, Result<Unit> &&result) {
|
||||
if (result.is_error()) {
|
||||
CHECK(G()->close_flag());
|
||||
promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return;
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
|
||||
const WebPage *web_page = get_web_page(web_page_id);
|
||||
if (web_page == nullptr) {
|
||||
reload_web_page_by_url(url, std::move(promise));
|
||||
return;
|
||||
return reload_web_page_by_url(url, std::move(promise));
|
||||
}
|
||||
|
||||
if (web_page->url != url) {
|
||||
on_get_web_page_by_url(url, web_page_id, true);
|
||||
}
|
||||
|
||||
promise.set_value(Unit());
|
||||
promise.set_value(WebPageId(web_page_id));
|
||||
}
|
||||
|
||||
void WebPagesManager::reload_web_page_by_url(const string &url, Promise<Unit> &&promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
|
||||
LOG(INFO) << "Reload url \"" << url << '"';
|
||||
void WebPagesManager::reload_web_page_by_url(const string &url, Promise<WebPageId> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
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";
|
||||
G()->td_db()->get_sqlite_pmc()->set(
|
||||
get_web_page_database_key(web_page_id), log_event_store(*web_page).as_slice().str(),
|
||||
PromiseCreator::lambda([web_page_id](Result<> result) {
|
||||
send_closure(G()->web_pages_manager(), &WebPagesManager::on_save_web_page_to_database, web_page_id,
|
||||
result.is_ok());
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](Result<> result) {
|
||||
send_closure(actor_id, &WebPagesManager::on_save_web_page_to_database, web_page_id, result.is_ok());
|
||||
}));
|
||||
}
|
||||
|
||||
@ -1594,11 +1576,11 @@ void WebPagesManager::load_web_page_from_database(WebPageId web_page_id, Promise
|
||||
auto &load_web_page_queries = load_web_page_from_database_queries_[web_page_id];
|
||||
load_web_page_queries.push_back(std::move(promise));
|
||||
if (load_web_page_queries.size() == 1u) {
|
||||
G()->td_db()->get_sqlite_pmc()->get(
|
||||
get_web_page_database_key(web_page_id), PromiseCreator::lambda([web_page_id](string value) {
|
||||
send_closure(G()->web_pages_manager(), &WebPagesManager::on_load_web_page_from_database, web_page_id,
|
||||
std::move(value));
|
||||
}));
|
||||
G()->td_db()->get_sqlite_pmc()->get(get_web_page_database_key(web_page_id),
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), web_page_id](string value) {
|
||||
send_closure(actor_id, &WebPagesManager::on_load_web_page_from_database,
|
||||
web_page_id, std::move(value));
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1620,7 +1602,7 @@ void WebPagesManager::on_load_web_page_from_database(WebPageId web_page_id, stri
|
||||
|
||||
LOG(INFO) << "Successfully loaded " << web_page_id << " of size " << value.size() << " from database";
|
||||
// G()->td_db()->get_sqlite_pmc()->erase(get_web_page_database_key(web_page_id), Auto());
|
||||
// return;
|
||||
// value.clear();
|
||||
|
||||
if (!have_web_page(web_page_id)) {
|
||||
if (!value.empty()) {
|
||||
|
@ -67,13 +67,13 @@ class WebPagesManager final : public Actor {
|
||||
|
||||
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, 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,
|
||||
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;
|
||||
|
||||
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(
|
||||
WebPageId web_page_id, const WebPageInstantView *web_page_instant_view) const;
|
||||
@ -153,22 +153,23 @@ class WebPagesManager final : public Actor {
|
||||
|
||||
static string get_web_page_instant_view_database_key(WebPageId web_page_id);
|
||||
|
||||
void load_web_page_instant_view(WebPageId web_page_id, bool force_full, Promise<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 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);
|
||||
|
||||
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,
|
||||
Result<> result);
|
||||
void on_load_web_page_by_url_from_database(WebPageId web_page_id, string url, Promise<WebPageId> &&promise,
|
||||
Result<Unit> &&result);
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
@ -186,8 +187,8 @@ class WebPagesManager final : public Actor {
|
||||
std::unordered_set<WebPageId, WebPageIdHash> loaded_from_database_web_pages_;
|
||||
|
||||
struct PendingWebPageInstantViewQueries {
|
||||
vector<Promise<Unit>> partial;
|
||||
vector<Promise<Unit>> full;
|
||||
vector<Promise<WebPageId>> partial;
|
||||
vector<Promise<WebPageId>> full;
|
||||
};
|
||||
std::unordered_map<WebPageId, PendingWebPageInstantViewQueries, WebPageIdHash> load_web_page_instant_view_queries_;
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "td/utils/format.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
#include "td/utils/ScopeGuard.h"
|
||||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/SliceBuilder.h"
|
||||
#include "td/utils/Status.h"
|
||||
@ -78,10 +77,7 @@ class FileDb final : public FileDbInterface {
|
||||
|
||||
void clear_file_data(FileDbId id, const string &remote_key, const string &local_key, const string &generate_key) {
|
||||
auto &pmc = file_pmc();
|
||||
pmc.begin_transaction().ensure();
|
||||
SCOPE_EXIT {
|
||||
pmc.commit_transaction().ensure();
|
||||
};
|
||||
pmc.begin_write_transaction().ensure();
|
||||
|
||||
if (id > current_pmc_id_) {
|
||||
pmc.set("file_id", to_string(id.get()));
|
||||
@ -89,27 +85,26 @@ class FileDb final : public FileDbInterface {
|
||||
}
|
||||
|
||||
pmc.erase(PSTRING() << "file" << id.get());
|
||||
LOG(DEBUG) << "ERASE " << format::as_hex_dump<4>(Slice(PSLICE() << "file" << id.get()));
|
||||
// LOG(DEBUG) << "ERASE " << format::as_hex_dump<4>(Slice(PSLICE() << "file" << id.get()));
|
||||
|
||||
if (!remote_key.empty()) {
|
||||
pmc.erase(remote_key);
|
||||
LOG(DEBUG) << "ERASE remote " << format::as_hex_dump<4>(Slice(remote_key));
|
||||
// LOG(DEBUG) << "ERASE remote " << format::as_hex_dump<4>(Slice(remote_key));
|
||||
}
|
||||
if (!local_key.empty()) {
|
||||
pmc.erase(local_key);
|
||||
LOG(DEBUG) << "ERASE local " << format::as_hex_dump<4>(Slice(local_key));
|
||||
// LOG(DEBUG) << "ERASE local " << format::as_hex_dump<4>(Slice(local_key));
|
||||
}
|
||||
if (!generate_key.empty()) {
|
||||
pmc.erase(generate_key);
|
||||
}
|
||||
|
||||
pmc.commit_transaction().ensure();
|
||||
}
|
||||
void store_file_data(FileDbId id, const string &file_data, const string &remote_key, const string &local_key,
|
||||
const string &generate_key) {
|
||||
auto &pmc = file_pmc();
|
||||
pmc.begin_transaction().ensure();
|
||||
SCOPE_EXIT {
|
||||
pmc.commit_transaction().ensure();
|
||||
};
|
||||
pmc.begin_write_transaction().ensure();
|
||||
|
||||
if (id > current_pmc_id_) {
|
||||
pmc.set("file_id", to_string(id.get()));
|
||||
@ -127,13 +122,12 @@ class FileDb final : public FileDbInterface {
|
||||
if (!generate_key.empty()) {
|
||||
pmc.set(generate_key, to_string(id.get()));
|
||||
}
|
||||
|
||||
pmc.commit_transaction().ensure();
|
||||
}
|
||||
void store_file_data_ref(FileDbId id, FileDbId new_id) {
|
||||
auto &pmc = file_pmc();
|
||||
pmc.begin_transaction().ensure();
|
||||
SCOPE_EXIT {
|
||||
pmc.commit_transaction().ensure();
|
||||
};
|
||||
pmc.begin_write_transaction().ensure();
|
||||
|
||||
if (id > current_pmc_id_) {
|
||||
pmc.set("file_id", to_string(id.get()));
|
||||
@ -141,18 +135,18 @@ class FileDb final : public FileDbInterface {
|
||||
}
|
||||
|
||||
do_store_file_data_ref(id, new_id);
|
||||
|
||||
pmc.commit_transaction().ensure();
|
||||
}
|
||||
|
||||
void optimize_refs(const std::vector<FileDbId> ids, FileDbId main_id) {
|
||||
LOG(INFO) << "Optimize " << ids.size() << " ids in file database to " << main_id.get();
|
||||
auto &pmc = file_pmc();
|
||||
pmc.begin_transaction().ensure();
|
||||
SCOPE_EXIT {
|
||||
pmc.commit_transaction().ensure();
|
||||
};
|
||||
pmc.begin_write_transaction().ensure();
|
||||
for (size_t i = 0; i + 1 < ids.size(); i++) {
|
||||
do_store_file_data_ref(ids[i], main_id);
|
||||
}
|
||||
pmc.commit_transaction().ensure();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -221,10 +215,10 @@ class FileDb final : public FileDbInterface {
|
||||
if (file_data.generate_ != nullptr && new_generate) {
|
||||
generate_key = as_key(*file_data.generate_);
|
||||
}
|
||||
LOG(DEBUG) << "SAVE " << id.get() << " -> " << file_data << " "
|
||||
<< tag("remote_key", format::as_hex_dump<4>(Slice(remote_key)))
|
||||
<< tag("local_key", format::as_hex_dump<4>(Slice(local_key)))
|
||||
<< tag("generate_key", format::as_hex_dump<4>(Slice(generate_key)));
|
||||
// LOG(DEBUG) << "SAVE " << id.get() << " -> " << file_data << " "
|
||||
// << tag("remote_key", format::as_hex_dump<4>(Slice(remote_key)))
|
||||
// << tag("local_key", format::as_hex_dump<4>(Slice(local_key)))
|
||||
// << tag("generate_key", format::as_hex_dump<4>(Slice(generate_key)));
|
||||
send_closure(file_db_actor_, &FileDbActor::store_file_data, id, serialize(file_data), remote_key, local_key,
|
||||
generate_key);
|
||||
}
|
||||
@ -243,7 +237,7 @@ class FileDb final : public FileDbInterface {
|
||||
|
||||
static Result<FileData> load_file_data_impl(ActorId<FileDbActor> file_db_actor_id, SqliteKeyValue &pmc,
|
||||
const string &key, FileDbId current_pmc_id) {
|
||||
//LOG(DEBUG) << "Load by key " << format::as_hex_dump<4>(Slice(key));
|
||||
// LOG(DEBUG) << "Load by key " << format::as_hex_dump<4>(Slice(key));
|
||||
TRY_RESULT(id, get_id(pmc, key));
|
||||
|
||||
vector<FileDbId> ids;
|
||||
@ -270,8 +264,8 @@ class FileDb final : public FileDbInterface {
|
||||
if (ids.size() > 1) {
|
||||
send_closure(file_db_actor_id, &FileDbActor::optimize_refs, std::move(ids), id);
|
||||
}
|
||||
//LOG(DEBUG) << "By ID " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str));
|
||||
//LOG(INFO) << attempt_count;
|
||||
// LOG(DEBUG) << "By ID " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str));
|
||||
// LOG(INFO) << attempt_count;
|
||||
|
||||
log_event::WithVersion<TlParser> parser(data_str);
|
||||
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 {
|
||||
auto id_str = pmc.get(key);
|
||||
//LOG(DEBUG) << "Found ID " << id_str << " by key " << format::as_hex_dump<4>(Slice(key));
|
||||
// LOG(DEBUG) << "Found ID " << id_str << " by key " << format::as_hex_dump<4>(Slice(key));
|
||||
if (id_str.empty()) {
|
||||
return Status::Error("There is no such a key in database");
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector<FullFi
|
||||
return false;
|
||||
});
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
|
||||
// sort by max(atime, mtime)
|
||||
@ -152,7 +152,7 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector<FullFi
|
||||
size_t pos = 0;
|
||||
while (pos < files.size() && (remove_count > 0 || remove_size > 0)) {
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
if (remove_count > 0) {
|
||||
remove_by_count_cnt++;
|
||||
|
@ -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,
|
||||
Promise<Unit> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
auto file_view = get_file_view(file_id);
|
||||
CHECK(!file_view.empty());
|
||||
if (result.is_ok() &&
|
||||
@ -2030,9 +2032,7 @@ void FileManager::get_content(FileId file_id, Promise<BufferSlice> promise) {
|
||||
|
||||
void FileManager::read_file_part(FileId file_id, int32 offset, int32 count, int left_tries,
|
||||
Promise<td_api::object_ptr<td_api::filePart>> promise) {
|
||||
if (G()->close_flag()) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
}
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
|
||||
if (!file_id.is_valid()) {
|
||||
return promise.set_error(Status::Error(400, "File identifier is invalid"));
|
||||
@ -2224,8 +2224,8 @@ void FileManager::run_download(FileNodePtr node, bool force_update_priority) {
|
||||
|
||||
if (priority == 0) {
|
||||
node->set_download_priority(priority);
|
||||
LOG(INFO) << "Cancel downloading of file " << node->main_file_id_;
|
||||
if (old_priority != 0) {
|
||||
LOG(INFO) << "Cancel downloading of file " << node->main_file_id_;
|
||||
do_cancel_download(node);
|
||||
}
|
||||
return;
|
||||
@ -2640,7 +2640,7 @@ void FileManager::run_generate(FileNodePtr node) {
|
||||
}
|
||||
FileView file_view(node);
|
||||
if (!file_view.can_generate()) {
|
||||
LOG(INFO) << "Skip run_generate, because file " << node->main_file_id_ << " can't be generated";
|
||||
// LOG(INFO) << "Skip run_generate, because file " << node->main_file_id_ << " can't be generated";
|
||||
return;
|
||||
}
|
||||
if (file_view.has_local_location()) {
|
||||
@ -2732,8 +2732,6 @@ void FileManager::run_upload(FileNodePtr node, std::vector<int> bad_parts) {
|
||||
if (old_priority != 0) {
|
||||
LOG(INFO) << "Cancel file " << file_id << " uploading";
|
||||
do_cancel_upload(node);
|
||||
} else {
|
||||
LOG(INFO) << "File " << file_id << " upload priority is still 0";
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -3872,7 +3870,7 @@ void FileManager::hangup() {
|
||||
while (!queries_container_.empty()) {
|
||||
auto ids = queries_container_.ids();
|
||||
for (auto id : ids) {
|
||||
on_error(id, Status::Error(500, "Request aborted"));
|
||||
on_error(id, Global::request_aborted_error());
|
||||
}
|
||||
}
|
||||
is_closed_ = true;
|
||||
|
@ -161,7 +161,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
|
||||
auto passed = Time::now() - start;
|
||||
LOG_IF(INFO, passed > 0.5) << "Get file stats took: " << format::as_time(passed);
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
promise.set_value(std::move(file_stats));
|
||||
} else {
|
||||
@ -182,7 +182,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
|
||||
});
|
||||
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
|
||||
std::unordered_map<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;
|
||||
pos++;
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
}
|
||||
scan_db(token_, [&](DbFileInfo &db_info) {
|
||||
@ -203,14 +203,14 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
|
||||
full_infos[it->second].owner_dialog_id = db_info.owner_dialog_id;
|
||||
});
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
|
||||
FileStats file_stats(need_all_files, split_by_owner_dialog_id);
|
||||
for (auto &full_info : full_infos) {
|
||||
file_stats.add(std::move(full_info));
|
||||
if (token_) {
|
||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||
return promise.set_error(Global::request_aborted_error());
|
||||
}
|
||||
}
|
||||
auto passed = Time::now() - start;
|
||||
|
@ -6,6 +6,7 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
@ -40,7 +41,7 @@ class NetActor : public NetQueryCallback {
|
||||
|
||||
class NetActorOnce : public NetActor {
|
||||
void hangup() override {
|
||||
on_error(0, Status::Error(500, "Request aborted"));
|
||||
on_error(0, Global::request_aborted_error());
|
||||
stop();
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ void NetQueryDelayer::on_slot_event(uint64 id) {
|
||||
|
||||
void NetQueryDelayer::tear_down() {
|
||||
container_.for_each([](auto id, auto &query_slot) {
|
||||
query_slot.query_->set_error(Status::Error(500, "Request aborted"));
|
||||
query_slot.query_->set_error(Global::request_aborted_error());
|
||||
G()->net_query_dispatcher().dispatch(std::move(query_slot.query_));
|
||||
});
|
||||
}
|
||||
|
@ -6,6 +6,8 @@
|
||||
//
|
||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||
|
||||
#include "td/telegram/ConfigShared.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/net/AuthDataShared.h"
|
||||
#include "td/telegram/net/DcAuthManager.h"
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
@ -13,9 +15,6 @@
|
||||
#include "td/telegram/net/PublicRsaKeyShared.h"
|
||||
#include "td/telegram/net/PublicRsaKeyWatchdog.h"
|
||||
#include "td/telegram/net/SessionMultiProxy.h"
|
||||
|
||||
#include "td/telegram/ConfigShared.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/TdDb.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
@ -44,7 +43,7 @@ void NetQueryDispatcher::complete_net_query(NetQueryPtr net_query) {
|
||||
void NetQueryDispatcher::dispatch(NetQueryPtr net_query) {
|
||||
// net_query->debug("dispatch");
|
||||
if (stop_flag_.load(std::memory_order_relaxed)) {
|
||||
net_query->set_error(Status::Error(500, "Request aborted"));
|
||||
net_query->set_error(Global::request_aborted_error());
|
||||
return complete_net_query(std::move(net_query));
|
||||
}
|
||||
if (G()->shared_config().get_option_boolean("test_flood_wait")) {
|
||||
|
@ -75,6 +75,7 @@ class Actor : public ObserverBase {
|
||||
void do_migrate(int32 sched_id);
|
||||
|
||||
uint64 get_link_token();
|
||||
std::weak_ptr<ActorContext> get_context_weak_ptr() const;
|
||||
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
|
||||
string set_tag(string tag);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ActorType>
|
||||
std::enable_if_t<std::is_base_of<Actor, ActorType>::value> finish_migrate(ActorType &obj) {
|
||||
if (!obj.empty()) {
|
||||
Scheduler::instance()->finish_migrate_actor(&obj);
|
||||
}
|
||||
}
|
||||
|
||||
inline uint64 Actor::get_link_token() {
|
||||
return Scheduler::instance()->get_link_token(this);
|
||||
}
|
||||
|
||||
inline std::weak_ptr<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) {
|
||||
return info_->set_context(std::move(context));
|
||||
}
|
||||
|
||||
inline string Actor::set_tag(string tag) {
|
||||
auto *ctx = info_->get_context();
|
||||
string old_tag;
|
||||
@ -105,12 +113,14 @@ inline string Actor::set_tag(string tag) {
|
||||
inline void Actor::init(ObjectPool<ActorInfo>::OwnerPtr &&info) {
|
||||
info_ = std::move(info);
|
||||
}
|
||||
|
||||
inline ActorInfo *Actor::get_info() {
|
||||
return &*info_;
|
||||
}
|
||||
inline const ActorInfo *Actor::get_info() const {
|
||||
return &*info_;
|
||||
}
|
||||
|
||||
inline ObjectPool<ActorInfo>::OwnerPtr Actor::clear() {
|
||||
return std::move(info_);
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ class ActorInfo final
|
||||
const Actor *get_actor_unsafe() const;
|
||||
|
||||
std::shared_ptr<ActorContext> set_context(std::shared_ptr<ActorContext> context);
|
||||
std::weak_ptr<ActorContext> get_context_weak_ptr() const;
|
||||
ActorContext *get_context();
|
||||
const ActorContext *get_context() const;
|
||||
CSlice get_name() const;
|
||||
|
@ -156,6 +156,11 @@ inline std::shared_ptr<ActorContext> ActorInfo::set_context(std::shared_ptr<Acto
|
||||
Scheduler::on_context_updated();
|
||||
return context;
|
||||
}
|
||||
|
||||
inline std::weak_ptr<ActorContext> ActorInfo::get_context_weak_ptr() const {
|
||||
return context_;
|
||||
}
|
||||
|
||||
inline const ActorContext *ActorInfo::get_context() const {
|
||||
return context_.get();
|
||||
}
|
||||
|
@ -13,31 +13,29 @@
|
||||
#include "td/utils/Random.h"
|
||||
#include "td/utils/tests.h"
|
||||
|
||||
using namespace td;
|
||||
|
||||
TEST(MultiTimeout, bug) {
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 0;
|
||||
sched.init(threads_n);
|
||||
|
||||
sched.start();
|
||||
unique_ptr<MultiTimeout> multi_timeout;
|
||||
td::unique_ptr<td::MultiTimeout> multi_timeout;
|
||||
struct Data {
|
||||
MultiTimeout *multi_timeout;
|
||||
td::MultiTimeout *multi_timeout;
|
||||
};
|
||||
Data data;
|
||||
|
||||
{
|
||||
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();
|
||||
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);
|
||||
if (key == 1) {
|
||||
data.multi_timeout->cancel_timeout(key + 1);
|
||||
data.multi_timeout->set_timeout_in(key + 2, 1);
|
||||
} else {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
});
|
||||
multi_timeout->set_callback_data(&data);
|
||||
@ -51,9 +49,9 @@ TEST(MultiTimeout, bug) {
|
||||
sched.finish();
|
||||
}
|
||||
|
||||
class TimeoutManager final : public Actor {
|
||||
class TimeoutManager final : public td::Actor {
|
||||
public:
|
||||
static int32 count;
|
||||
static td::int32 count;
|
||||
|
||||
TimeoutManager() {
|
||||
count++;
|
||||
@ -70,7 +68,7 @@ class TimeoutManager final : public Actor {
|
||||
LOG(INFO) << "Destroy TimeoutManager";
|
||||
}
|
||||
|
||||
static void on_test_timeout_callback(void *timeout_manager_ptr, int64 id) {
|
||||
static void on_test_timeout_callback(void *timeout_manager_ptr, td::int64 id) {
|
||||
CHECK(count >= 0);
|
||||
if (count == 0) {
|
||||
LOG(ERROR) << "Receive timeout after manager was closed";
|
||||
@ -84,21 +82,21 @@ class TimeoutManager final : public Actor {
|
||||
void test_timeout() {
|
||||
CHECK(count > 0);
|
||||
// we must yield scheduler, so run_main breaks immediately, if timeouts are handled immediately
|
||||
Scheduler::instance()->yield();
|
||||
td::Scheduler::instance()->yield();
|
||||
}
|
||||
|
||||
MultiTimeout test_timeout_{"TestTimeout"};
|
||||
td::MultiTimeout test_timeout_{"TestTimeout"};
|
||||
};
|
||||
|
||||
int32 TimeoutManager::count;
|
||||
td::int32 TimeoutManager::count;
|
||||
|
||||
TEST(MultiTimeout, Destroy) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 0;
|
||||
sched.init(threads_n);
|
||||
|
||||
ActorOwn<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();
|
||||
sched.start();
|
||||
int cnt = 100;
|
||||
@ -107,12 +105,12 @@ TEST(MultiTimeout, Destroy) {
|
||||
cnt--;
|
||||
if (cnt > 0) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
manager->test_timeout_.set_timeout_in(Random::fast(0, 1000000000), Random::fast(2, 5) / 1000.0);
|
||||
manager->test_timeout_.set_timeout_in(td::Random::fast(0, 1000000000), td::Random::fast(2, 5) / 1000.0);
|
||||
}
|
||||
} else if (cnt == 0) {
|
||||
timeout_manager.reset();
|
||||
} else if (cnt == -10) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
}
|
||||
sched.finish();
|
||||
|
@ -19,18 +19,16 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
using namespace td;
|
||||
|
||||
namespace {
|
||||
|
||||
template <class ContainerT>
|
||||
static typename ContainerT::value_type &rand_elem(ContainerT &cont) {
|
||||
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) {
|
||||
uint32 res = 1;
|
||||
static td::uint32 fast_pow_mod_uint32(td::uint32 x, td::uint32 p) {
|
||||
td::uint32 res = 1;
|
||||
while (p) {
|
||||
if (p & 1) {
|
||||
res *= x;
|
||||
@ -41,18 +39,18 @@ static uint32 fast_pow_mod_uint32(uint32 x, uint32 p) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static uint32 slow_pow_mod_uint32(uint32 x, uint32 p) {
|
||||
uint32 res = 1;
|
||||
for (uint32 i = 0; i < p; i++) {
|
||||
static td::uint32 slow_pow_mod_uint32(td::uint32 x, td::uint32 p) {
|
||||
td::uint32 res = 1;
|
||||
for (td::uint32 i = 0; i < p; i++) {
|
||||
res *= x;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct Query {
|
||||
uint32 query_id{};
|
||||
uint32 result{};
|
||||
std::vector<int> todo;
|
||||
td::uint32 query_id{};
|
||||
td::uint32 result{};
|
||||
td::vector<int> todo;
|
||||
Query() = default;
|
||||
Query(const Query &) = delete;
|
||||
Query &operator=(const Query &) = delete;
|
||||
@ -72,25 +70,25 @@ struct Query {
|
||||
}
|
||||
};
|
||||
|
||||
static uint32 fast_calc(Query &q) {
|
||||
uint32 result = q.result;
|
||||
static td::uint32 fast_calc(Query &q) {
|
||||
td::uint32 result = q.result;
|
||||
for (auto x : q.todo) {
|
||||
result = fast_pow_mod_uint32(result, x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class Worker final : public Actor {
|
||||
class Worker final : public td::Actor {
|
||||
public:
|
||||
explicit Worker(int threads_n) : threads_n_(threads_n) {
|
||||
}
|
||||
void query(PromiseActor<uint32> &&promise, uint32 x, uint32 p) {
|
||||
uint32 result = slow_pow_mod_uint32(x, p);
|
||||
void query(td::PromiseActor<td::uint32> &&promise, td::uint32 x, td::uint32 p) {
|
||||
td::uint32 result = slow_pow_mod_uint32(x, p);
|
||||
promise.set_value(std::move(result));
|
||||
|
||||
(void)threads_n_;
|
||||
// if (threads_n_ > 1 && Random::fast(0, 9) == 0) {
|
||||
// migrate(Random::fast(2, threads_n));
|
||||
// if (threads_n_ > 1 && td::Random::fast(0, 9) == 0) {
|
||||
// migrate(td::Random::fast(2, threads_n));
|
||||
//}
|
||||
}
|
||||
|
||||
@ -98,7 +96,7 @@ class Worker final : public Actor {
|
||||
int threads_n_;
|
||||
};
|
||||
|
||||
class QueryActor final : public Actor {
|
||||
class QueryActor final : public td::Actor {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
@ -115,39 +113,39 @@ class QueryActor final : public Actor {
|
||||
explicit QueryActor(int threads_n) : threads_n_(threads_n) {
|
||||
}
|
||||
|
||||
void set_callback(unique_ptr<Callback> callback) {
|
||||
void set_callback(td::unique_ptr<Callback> 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);
|
||||
}
|
||||
|
||||
void query(Query &&query) {
|
||||
uint32 x = query.result;
|
||||
uint32 p = query.next_pow();
|
||||
if (Random::fast(0, 3) && (p <= 1000 || workers_.empty())) {
|
||||
td::uint32 x = query.result;
|
||||
td::uint32 p = query.next_pow();
|
||||
if (td::Random::fast(0, 3) && (p <= 1000 || workers_.empty())) {
|
||||
query.result = slow_pow_mod_uint32(x, p);
|
||||
callback_->on_result(std::move(query));
|
||||
} else {
|
||||
auto future = Random::fast(0, 3) == 0
|
||||
? send_promise<ActorSendType::Immediate>(rand_elem(workers_), &Worker::query, x, p)
|
||||
: send_promise<ActorSendType::Later>(rand_elem(workers_), &Worker::query, x, p);
|
||||
auto future = td::Random::fast(0, 3) == 0
|
||||
? td::send_promise<td::ActorSendType::Immediate>(rand_elem(workers_), &Worker::query, x, p)
|
||||
: td::send_promise<td::ActorSendType::Later>(rand_elem(workers_), &Worker::query, x, p);
|
||||
if (future.is_ready()) {
|
||||
query.result = future.move_as_ok();
|
||||
callback_->on_result(std::move(query));
|
||||
} else {
|
||||
future.set_event(EventCreator::raw(actor_id(), query.query_id));
|
||||
future.set_event(td::EventCreator::raw(actor_id(), query.query_id));
|
||||
auto query_id = query.query_id;
|
||||
pending_.emplace(query_id, std::make_pair(std::move(future), std::move(query)));
|
||||
}
|
||||
}
|
||||
if (threads_n_ > 1 && Random::fast(0, 9) == 0) {
|
||||
migrate(Random::fast(2, threads_n_));
|
||||
if (threads_n_ > 1 && td::Random::fast(0, 9) == 0) {
|
||||
migrate(td::Random::fast(2, threads_n_));
|
||||
}
|
||||
}
|
||||
|
||||
void raw_event(const Event::Raw &event) final {
|
||||
uint32 id = event.u32;
|
||||
void raw_event(const td::Event::Raw &event) final {
|
||||
td::uint32 id = event.u32;
|
||||
auto it = pending_.find(id);
|
||||
auto future = std::move(it->second.first);
|
||||
auto query = std::move(it->second.second);
|
||||
@ -162,7 +160,7 @@ class QueryActor final : public Actor {
|
||||
stop();
|
||||
}
|
||||
|
||||
void on_start_migrate(int32 sched_id) final {
|
||||
void on_start_migrate(td::int32 sched_id) final {
|
||||
for (auto &it : pending_) {
|
||||
start_migrate(it.second.first, sched_id);
|
||||
}
|
||||
@ -174,13 +172,13 @@ class QueryActor final : public Actor {
|
||||
}
|
||||
|
||||
private:
|
||||
unique_ptr<Callback> callback_;
|
||||
std::map<uint32, std::pair<FutureActor<uint32>, Query>> pending_;
|
||||
std::vector<ActorId<Worker>> workers_;
|
||||
td::unique_ptr<Callback> callback_;
|
||||
std::map<td::uint32, std::pair<td::FutureActor<td::uint32>, Query>> pending_;
|
||||
td::vector<td::ActorId<Worker>> workers_;
|
||||
int threads_n_;
|
||||
};
|
||||
|
||||
class MainQueryActor final : public Actor {
|
||||
class MainQueryActor final : public td::Actor {
|
||||
class QueryActorCallback final : public QueryActor::Callback {
|
||||
public:
|
||||
void on_result(Query &&query) final {
|
||||
@ -193,13 +191,13 @@ class MainQueryActor final : public Actor {
|
||||
void on_closed() final {
|
||||
send_closure(parent_id_, &MainQueryActor::on_closed);
|
||||
}
|
||||
QueryActorCallback(ActorId<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) {
|
||||
}
|
||||
|
||||
private:
|
||||
ActorId<MainQueryActor> parent_id_;
|
||||
ActorId<QueryActor> next_solver_;
|
||||
td::ActorId<MainQueryActor> parent_id_;
|
||||
td::ActorId<QueryActor> next_solver_;
|
||||
};
|
||||
|
||||
const int ACTORS_CNT = 10;
|
||||
@ -212,22 +210,22 @@ class MainQueryActor final : public Actor {
|
||||
void start_up() final {
|
||||
actors_.resize(ACTORS_CNT);
|
||||
for (auto &actor : actors_) {
|
||||
auto actor_ptr = make_unique<QueryActor>(threads_n_);
|
||||
actor = register_actor("QueryActor", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0)
|
||||
auto actor_ptr = td::make_unique<QueryActor>(threads_n_);
|
||||
actor = register_actor("QueryActor", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0)
|
||||
.release();
|
||||
}
|
||||
|
||||
workers_.resize(WORKERS_CNT);
|
||||
for (auto &worker : workers_) {
|
||||
auto actor_ptr = make_unique<Worker>(threads_n_);
|
||||
worker =
|
||||
register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0).release();
|
||||
auto actor_ptr = td::make_unique<Worker>(threads_n_);
|
||||
worker = register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0)
|
||||
.release();
|
||||
}
|
||||
|
||||
for (int i = 0; i < ACTORS_CNT; i++) {
|
||||
ref_cnt_++;
|
||||
send_closure(actors_[i], &QueryActor::set_callback,
|
||||
make_unique<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_);
|
||||
}
|
||||
yield();
|
||||
@ -252,14 +250,14 @@ class MainQueryActor final : public Actor {
|
||||
void on_closed() {
|
||||
ref_cnt_--;
|
||||
if (ref_cnt_ == 0) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
}
|
||||
|
||||
void wakeup() final {
|
||||
int cnt = 100000;
|
||||
while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) {
|
||||
if (Random::fast_bool()) {
|
||||
if (td::Random::fast_bool()) {
|
||||
send_closure(rand_elem(actors_), &QueryActor::query, create_query());
|
||||
} else {
|
||||
send_closure_later(rand_elem(actors_), &QueryActor::query, create_query());
|
||||
@ -276,9 +274,9 @@ class MainQueryActor final : public Actor {
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<uint32, uint32> expected_;
|
||||
std::vector<ActorId<QueryActor>> actors_;
|
||||
std::vector<ActorId<Worker>> workers_;
|
||||
std::map<td::uint32, td::uint32> expected_;
|
||||
td::vector<td::ActorId<QueryActor>> actors_;
|
||||
td::vector<td::ActorId<Worker>> workers_;
|
||||
int out_cnt_ = 0;
|
||||
int in_cnt_ = 0;
|
||||
int query_id_ = 1;
|
||||
@ -286,46 +284,47 @@ class MainQueryActor final : public Actor {
|
||||
int threads_n_;
|
||||
};
|
||||
|
||||
class SimpleActor final : public Actor {
|
||||
class SimpleActor final : public td::Actor {
|
||||
public:
|
||||
explicit SimpleActor(int32 threads_n) : threads_n_(threads_n) {
|
||||
explicit SimpleActor(td::int32 threads_n) : threads_n_(threads_n) {
|
||||
}
|
||||
void start_up() final {
|
||||
auto actor_ptr = make_unique<Worker>(threads_n_);
|
||||
auto actor_ptr = td::make_unique<Worker>(threads_n_);
|
||||
worker_ =
|
||||
register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? Random::fast(2, threads_n_) : 0).release();
|
||||
register_actor("Worker", std::move(actor_ptr), threads_n_ > 1 ? td::Random::fast(2, threads_n_) : 0).release();
|
||||
yield();
|
||||
}
|
||||
|
||||
void wakeup() final {
|
||||
if (q_ == 100000) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
q_++;
|
||||
p_ = Random::fast_bool() ? 1 : 10000;
|
||||
auto future = Random::fast(0, 3) == 0 ? send_promise<ActorSendType::Immediate>(worker_, &Worker::query, q_, p_)
|
||||
: send_promise<ActorSendType::Later>(worker_, &Worker::query, q_, p_);
|
||||
p_ = td::Random::fast_bool() ? 1 : 10000;
|
||||
auto future = td::Random::fast(0, 3) == 0
|
||||
? 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()) {
|
||||
auto result = future.move_as_ok();
|
||||
CHECK(result == fast_pow_mod_uint32(q_, p_));
|
||||
yield();
|
||||
} else {
|
||||
future.set_event(EventCreator::raw(actor_id(), nullptr));
|
||||
future.set_event(td::EventCreator::raw(actor_id(), nullptr));
|
||||
future_ = std::move(future);
|
||||
}
|
||||
// if (threads_n_ > 1 && Random::fast(0, 2) == 0) {
|
||||
// migrate(Random::fast(1, threads_n));
|
||||
// if (threads_n_ > 1 && td::Random::fast(0, 2) == 0) {
|
||||
// migrate(td::Random::fast(1, threads_n));
|
||||
//}
|
||||
}
|
||||
void raw_event(const Event::Raw &event) final {
|
||||
void raw_event(const td::Event::Raw &event) final {
|
||||
auto result = future_.move_as_ok();
|
||||
CHECK(result == fast_pow_mod_uint32(q_, p_));
|
||||
yield();
|
||||
}
|
||||
|
||||
void on_start_migrate(int32 sched_id) final {
|
||||
void on_start_migrate(td::int32 sched_id) final {
|
||||
start_migrate(future_, sched_id);
|
||||
}
|
||||
void on_finish_migrate() final {
|
||||
@ -333,25 +332,26 @@ class SimpleActor final : public Actor {
|
||||
}
|
||||
|
||||
private:
|
||||
int32 threads_n_;
|
||||
ActorId<Worker> worker_;
|
||||
FutureActor<uint32> future_;
|
||||
uint32 q_ = 1;
|
||||
uint32 p_ = 0;
|
||||
td::int32 threads_n_;
|
||||
td::ActorId<Worker> worker_;
|
||||
td::FutureActor<td::uint32> future_;
|
||||
td::uint32 q_ = 1;
|
||||
td::uint32 p_ = 0;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
class SendToDead final : public Actor {
|
||||
class SendToDead final : public td::Actor {
|
||||
public:
|
||||
class Parent final : public Actor {
|
||||
class Parent final : public td::Actor {
|
||||
public:
|
||||
explicit Parent(ActorShared<> parent, int ttl = 3) : parent_(std::move(parent)), ttl_(ttl) {
|
||||
explicit Parent(td::ActorShared<> parent, int ttl = 3) : parent_(std::move(parent)), ttl_(ttl) {
|
||||
}
|
||||
void start_up() final {
|
||||
set_timeout_in(Random::fast_uint32() % 3 * 0.001);
|
||||
set_timeout_in(td::Random::fast_uint32() % 3 * 0.001);
|
||||
if (ttl_ != 0) {
|
||||
child_ = create_actor_on_scheduler<Parent>(
|
||||
"Child", Random::fast_uint32() % Scheduler::instance()->sched_count(), actor_shared(this), ttl_ - 1);
|
||||
child_ = td::create_actor_on_scheduler<Parent>(
|
||||
"Child", td::Random::fast_uint32() % td::Scheduler::instance()->sched_count(), actor_shared(this),
|
||||
ttl_ - 1);
|
||||
}
|
||||
}
|
||||
void timeout_expired() final {
|
||||
@ -359,29 +359,30 @@ class SendToDead final : public Actor {
|
||||
}
|
||||
|
||||
private:
|
||||
ActorOwn<Parent> child_;
|
||||
ActorShared<> parent_;
|
||||
td::ActorOwn<Parent> child_;
|
||||
td::ActorShared<> parent_;
|
||||
int ttl_;
|
||||
};
|
||||
|
||||
void start_up() final {
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
create_actor_on_scheduler<Parent>("Parent", Random::fast_uint32() % Scheduler::instance()->sched_count(),
|
||||
create_reference(), 4)
|
||||
td::create_actor_on_scheduler<Parent>(
|
||||
"Parent", td::Random::fast_uint32() % td::Scheduler::instance()->sched_count(), create_reference(), 4)
|
||||
.release();
|
||||
}
|
||||
}
|
||||
|
||||
ActorShared<> create_reference() {
|
||||
td::ActorShared<> create_reference() {
|
||||
ref_cnt_++;
|
||||
return actor_shared(this);
|
||||
}
|
||||
|
||||
void hangup_shared() final {
|
||||
ref_cnt_--;
|
||||
if (ref_cnt_ == 0) {
|
||||
ttl_--;
|
||||
if (ttl_ <= 0) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
stop();
|
||||
} else {
|
||||
start_up();
|
||||
@ -389,14 +390,14 @@ class SendToDead final : public Actor {
|
||||
}
|
||||
}
|
||||
|
||||
uint32 ttl_{50};
|
||||
uint32 ref_cnt_{0};
|
||||
td::uint32 ttl_{50};
|
||||
td::uint32 ref_cnt_{0};
|
||||
};
|
||||
|
||||
TEST(Actors, send_to_dead) {
|
||||
//TODO: fix CHECK(storage_count_.load() == 0)
|
||||
return;
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 5;
|
||||
sched.init(threads_n);
|
||||
|
||||
@ -409,9 +410,7 @@ TEST(Actors, send_to_dead) {
|
||||
}
|
||||
|
||||
TEST(Actors, main_simple) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 3;
|
||||
sched.init(threads_n);
|
||||
|
||||
@ -424,9 +423,7 @@ TEST(Actors, main_simple) {
|
||||
}
|
||||
|
||||
TEST(Actors, main) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 9;
|
||||
sched.init(threads_n);
|
||||
|
||||
@ -438,23 +435,21 @@ TEST(Actors, main) {
|
||||
sched.finish();
|
||||
}
|
||||
|
||||
class DoAfterStop final : public Actor {
|
||||
class DoAfterStop final : public td::Actor {
|
||||
public:
|
||||
void loop() final {
|
||||
ptr = make_unique<int>(10);
|
||||
ptr = td::make_unique<int>(10);
|
||||
stop();
|
||||
CHECK(*ptr == 10);
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
|
||||
private:
|
||||
unique_ptr<int> ptr;
|
||||
td::unique_ptr<int> ptr;
|
||||
};
|
||||
|
||||
TEST(Actors, do_after_stop) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 0;
|
||||
sched.init(threads_n);
|
||||
|
||||
@ -466,9 +461,9 @@ TEST(Actors, do_after_stop) {
|
||||
sched.finish();
|
||||
}
|
||||
|
||||
class XContext final : public ActorContext {
|
||||
class XContext final : public td::ActorContext {
|
||||
public:
|
||||
int32 get_id() const final {
|
||||
td::int32 get_id() const final {
|
||||
return 123456789;
|
||||
}
|
||||
|
||||
@ -481,12 +476,12 @@ class XContext final : public ActorContext {
|
||||
int x = 1234;
|
||||
};
|
||||
|
||||
class WithXContext final : public Actor {
|
||||
class WithXContext final : public td::Actor {
|
||||
public:
|
||||
void start_up() final {
|
||||
auto old_context = set_context(std::make_shared<XContext>());
|
||||
}
|
||||
void f(unique_ptr<Guard> guard) {
|
||||
void f(td::unique_ptr<td::Guard> guard) {
|
||||
}
|
||||
void close() {
|
||||
stop();
|
||||
@ -494,25 +489,23 @@ class WithXContext final : public Actor {
|
||||
};
|
||||
|
||||
static void check_context() {
|
||||
auto ptr = static_cast<XContext *>(Scheduler::context());
|
||||
CHECK(ptr);
|
||||
auto ptr = static_cast<XContext *>(td::Scheduler::context());
|
||||
CHECK(ptr != nullptr);
|
||||
ptr->validate();
|
||||
}
|
||||
|
||||
TEST(Actors, context_during_destruction) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
int threads_n = 0;
|
||||
sched.init(threads_n);
|
||||
|
||||
{
|
||||
auto guard = sched.get_main_guard();
|
||||
auto with_context = create_actor<WithXContext>("WithXContext").release();
|
||||
send_closure(with_context, &WithXContext::f, create_lambda_guard([] { check_context(); }));
|
||||
auto with_context = td::create_actor<WithXContext>("WithXContext").release();
|
||||
send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { check_context(); }));
|
||||
send_closure_later(with_context, &WithXContext::close);
|
||||
send_closure(with_context, &WithXContext::f, create_lambda_guard([] { check_context(); }));
|
||||
send_closure(with_context, &WithXContext::f, create_lambda_guard([] { Scheduler::instance()->finish(); }));
|
||||
send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { check_context(); }));
|
||||
send_closure(with_context, &WithXContext::f, td::create_lambda_guard([] { td::Scheduler::instance()->finish(); }));
|
||||
}
|
||||
sched.start();
|
||||
while (sched.run_main(10)) {
|
||||
|
@ -28,40 +28,38 @@
|
||||
#include <tuple>
|
||||
|
||||
namespace {
|
||||
using namespace td;
|
||||
|
||||
static const size_t BUF_SIZE = 1024 * 1024;
|
||||
static char buf[BUF_SIZE];
|
||||
static char buf2[BUF_SIZE];
|
||||
static StringBuilder sb(MutableSlice(buf, BUF_SIZE - 1));
|
||||
static StringBuilder sb2(MutableSlice(buf2, BUF_SIZE - 1));
|
||||
static td::StringBuilder sb(td::MutableSlice(buf, BUF_SIZE - 1));
|
||||
static td::StringBuilder sb2(td::MutableSlice(buf2, BUF_SIZE - 1));
|
||||
|
||||
static auto create_queue() {
|
||||
auto res = std::make_shared<MpscPollableQueue<EventFull>>();
|
||||
static std::shared_ptr<td::MpscPollableQueue<td::EventFull>> create_queue() {
|
||||
auto res = std::make_shared<td::MpscPollableQueue<td::EventFull>>();
|
||||
res->init();
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(Actors, SendLater) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
sb.clear();
|
||||
Scheduler scheduler;
|
||||
td::Scheduler scheduler;
|
||||
scheduler.init(0, {create_queue()}, nullptr);
|
||||
|
||||
auto guard = scheduler.get_guard();
|
||||
class Worker final : public Actor {
|
||||
class Worker final : public td::Actor {
|
||||
public:
|
||||
void f() {
|
||||
sb << "A";
|
||||
}
|
||||
};
|
||||
auto id = create_actor<Worker>("Worker");
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
send_closure(id, &Worker::f);
|
||||
send_closure_later(id, &Worker::f);
|
||||
send_closure(id, &Worker::f);
|
||||
auto id = td::create_actor<Worker>("Worker");
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
td::send_closure(id, &Worker::f);
|
||||
td::send_closure_later(id, &Worker::f);
|
||||
td::send_closure(id, &Worker::f);
|
||||
ASSERT_STREQ("A", sb.as_cslice().c_str());
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
ASSERT_STREQ("AAA", sb.as_cslice().c_str());
|
||||
}
|
||||
|
||||
@ -87,7 +85,7 @@ class X {
|
||||
~X() = default;
|
||||
};
|
||||
|
||||
class XReceiver final : public Actor {
|
||||
class XReceiver final : public td::Actor {
|
||||
public:
|
||||
void by_const_ref(const X &) {
|
||||
sb << "[by_const_ref]";
|
||||
@ -101,13 +99,12 @@ class XReceiver final : public Actor {
|
||||
};
|
||||
|
||||
TEST(Actors, simple_pass_event_arguments) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
Scheduler scheduler;
|
||||
td::Scheduler scheduler;
|
||||
scheduler.init(0, {create_queue()}, nullptr);
|
||||
|
||||
auto guard = scheduler.get_guard();
|
||||
auto id = create_actor<XReceiver>("XR").release();
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
auto id = td::create_actor<XReceiver>("XR").release();
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
|
||||
X x;
|
||||
|
||||
@ -122,47 +119,47 @@ TEST(Actors, simple_pass_event_arguments) {
|
||||
|
||||
// Tmp-->ConstRef
|
||||
sb.clear();
|
||||
send_closure(id, &XReceiver::by_const_ref, X());
|
||||
td::send_closure(id, &XReceiver::by_const_ref, X());
|
||||
ASSERT_STREQ("[cnstr_default][by_const_ref]", sb.as_cslice().c_str());
|
||||
|
||||
// Tmp-->ConstRef (Delayed)
|
||||
sb.clear();
|
||||
send_closure_later(id, &XReceiver::by_const_ref, X());
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
td::send_closure_later(id, &XReceiver::by_const_ref, X());
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
// LOG(ERROR) << sb.as_cslice();
|
||||
ASSERT_STREQ("[cnstr_default][cnstr_move][by_const_ref]", sb.as_cslice().c_str());
|
||||
|
||||
// Tmp-->LvalueRef
|
||||
sb.clear();
|
||||
send_closure(id, &XReceiver::by_lvalue_ref, X());
|
||||
td::send_closure(id, &XReceiver::by_lvalue_ref, X());
|
||||
ASSERT_STREQ("[cnstr_default][by_lvalue_ref]", sb.as_cslice().c_str());
|
||||
|
||||
// Tmp-->LvalueRef (Delayed)
|
||||
sb.clear();
|
||||
send_closure_later(id, &XReceiver::by_lvalue_ref, X());
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
td::send_closure_later(id, &XReceiver::by_lvalue_ref, X());
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
ASSERT_STREQ("[cnstr_default][cnstr_move][by_lvalue_ref]", sb.as_cslice().c_str());
|
||||
|
||||
// Tmp-->Value
|
||||
sb.clear();
|
||||
send_closure(id, &XReceiver::by_value, X());
|
||||
td::send_closure(id, &XReceiver::by_value, X());
|
||||
ASSERT_STREQ("[cnstr_default][cnstr_move][by_value]", sb.as_cslice().c_str());
|
||||
|
||||
// Tmp-->Value (Delayed)
|
||||
sb.clear();
|
||||
send_closure_later(id, &XReceiver::by_value, X());
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
td::send_closure_later(id, &XReceiver::by_value, X());
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
ASSERT_STREQ("[cnstr_default][cnstr_move][cnstr_move][by_value]", sb.as_cslice().c_str());
|
||||
|
||||
// Var-->ConstRef
|
||||
sb.clear();
|
||||
send_closure(id, &XReceiver::by_const_ref, x);
|
||||
td::send_closure(id, &XReceiver::by_const_ref, x);
|
||||
ASSERT_STREQ("[by_const_ref]", sb.as_cslice().c_str());
|
||||
|
||||
// Var-->ConstRef (Delayed)
|
||||
sb.clear();
|
||||
send_closure_later(id, &XReceiver::by_const_ref, x);
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
td::send_closure_later(id, &XReceiver::by_const_ref, x);
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
ASSERT_STREQ("[cnstr_copy][by_const_ref]", sb.as_cslice().c_str());
|
||||
|
||||
// Var-->LvalueRef
|
||||
@ -171,17 +168,17 @@ TEST(Actors, simple_pass_event_arguments) {
|
||||
|
||||
// Var-->Value
|
||||
sb.clear();
|
||||
send_closure(id, &XReceiver::by_value, x);
|
||||
td::send_closure(id, &XReceiver::by_value, x);
|
||||
ASSERT_STREQ("[cnstr_copy][by_value]", sb.as_cslice().c_str());
|
||||
|
||||
// Var-->Value (Delayed)
|
||||
sb.clear();
|
||||
send_closure_later(id, &XReceiver::by_value, x);
|
||||
scheduler.run_no_guard(Timestamp::now());
|
||||
td::send_closure_later(id, &XReceiver::by_value, x);
|
||||
scheduler.run_no_guard(td::Timestamp::in(1));
|
||||
ASSERT_STREQ("[cnstr_copy][cnstr_move][by_value]", sb.as_cslice().c_str());
|
||||
}
|
||||
|
||||
class PrintChar final : public Actor {
|
||||
class PrintChar final : public td::Actor {
|
||||
public:
|
||||
PrintChar(char c, int cnt) : char_(c), cnt_(cnt) {
|
||||
}
|
||||
@ -208,19 +205,18 @@ class PrintChar final : public Actor {
|
||||
// Yield must add actor to the end of queue
|
||||
//
|
||||
TEST(Actors, simple_hand_yield) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
Scheduler scheduler;
|
||||
td::Scheduler scheduler;
|
||||
scheduler.init(0, {create_queue()}, nullptr);
|
||||
sb.clear();
|
||||
int cnt = 1000;
|
||||
{
|
||||
auto guard = scheduler.get_guard();
|
||||
create_actor<PrintChar>("PrintA", 'A', cnt).release();
|
||||
create_actor<PrintChar>("PrintB", 'B', cnt).release();
|
||||
create_actor<PrintChar>("PrintC", 'C', cnt).release();
|
||||
td::create_actor<PrintChar>("PrintA", 'A', cnt).release();
|
||||
td::create_actor<PrintChar>("PrintB", 'B', cnt).release();
|
||||
td::create_actor<PrintChar>("PrintC", 'C', cnt).release();
|
||||
}
|
||||
scheduler.run(Timestamp::now());
|
||||
std::string expected;
|
||||
scheduler.run(td::Timestamp::in(1));
|
||||
td::string expected;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
expected += "ABC";
|
||||
}
|
||||
@ -229,7 +225,7 @@ TEST(Actors, simple_hand_yield) {
|
||||
|
||||
class Ball {
|
||||
public:
|
||||
friend void start_migrate(Ball &ball, int32 sched_id) {
|
||||
friend void start_migrate(Ball &ball, td::int32 sched_id) {
|
||||
sb << "start";
|
||||
}
|
||||
friend void finish_migrate(Ball &ball) {
|
||||
@ -237,30 +233,30 @@ class Ball {
|
||||
}
|
||||
};
|
||||
|
||||
class Pong final : public Actor {
|
||||
class Pong final : public td::Actor {
|
||||
public:
|
||||
void pong(Ball ball) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
};
|
||||
|
||||
class Ping final : public Actor {
|
||||
class Ping final : public td::Actor {
|
||||
public:
|
||||
explicit Ping(ActorId<Pong> pong) : pong_(pong) {
|
||||
explicit Ping(td::ActorId<Pong> pong) : pong_(pong) {
|
||||
}
|
||||
void start_up() final {
|
||||
send_closure(pong_, &Pong::pong, Ball());
|
||||
td::send_closure(pong_, &Pong::pong, Ball());
|
||||
}
|
||||
|
||||
private:
|
||||
ActorId<Pong> pong_;
|
||||
td::ActorId<Pong> pong_;
|
||||
};
|
||||
|
||||
TEST(Actors, simple_migrate) {
|
||||
sb.clear();
|
||||
sb2.clear();
|
||||
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(2);
|
||||
auto pong = scheduler.create_actor_unsafe<Pong>(2, "Pong").release();
|
||||
scheduler.create_actor_unsafe<Ping>(1, "Ping", pong).release();
|
||||
@ -277,7 +273,7 @@ TEST(Actors, simple_migrate) {
|
||||
#endif
|
||||
}
|
||||
|
||||
class OpenClose final : public Actor {
|
||||
class OpenClose final : public td::Actor {
|
||||
public:
|
||||
explicit OpenClose(int cnt) : cnt_(cnt) {
|
||||
}
|
||||
@ -285,17 +281,17 @@ class OpenClose final : public Actor {
|
||||
yield();
|
||||
}
|
||||
void wakeup() final {
|
||||
ObserverBase *observer = reinterpret_cast<ObserverBase *>(123);
|
||||
auto observer = reinterpret_cast<td::ObserverBase *>(123);
|
||||
if (cnt_ > 0) {
|
||||
auto r_file_fd = FileFd::open("server", FileFd::Read | FileFd::Create);
|
||||
auto r_file_fd = td::FileFd::open("server", td::FileFd::Read | td::FileFd::Create);
|
||||
LOG_CHECK(r_file_fd.is_ok()) << r_file_fd.error();
|
||||
auto file_fd = r_file_fd.move_as_ok();
|
||||
{ PollableFd pollable_fd = file_fd.get_poll_info().extract_pollable_fd(observer); }
|
||||
{ auto pollable_fd = file_fd.get_poll_info().extract_pollable_fd(observer); }
|
||||
file_fd.close();
|
||||
cnt_--;
|
||||
yield();
|
||||
} else {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,8 +300,7 @@ class OpenClose final : public Actor {
|
||||
};
|
||||
|
||||
TEST(Actors, open_close) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(2);
|
||||
int cnt = 1000000;
|
||||
#if TD_WINDOWS || TD_ANDROID
|
||||
@ -321,18 +316,18 @@ TEST(Actors, open_close) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
class MsgActor : public Actor {
|
||||
class MsgActor : public td::Actor {
|
||||
public:
|
||||
virtual void msg() = 0;
|
||||
};
|
||||
|
||||
class Slave final : public Actor {
|
||||
class Slave final : public td::Actor {
|
||||
public:
|
||||
ActorId<MsgActor> msg;
|
||||
explicit Slave(ActorId<MsgActor> msg) : msg(msg) {
|
||||
td::ActorId<MsgActor> msg;
|
||||
explicit Slave(td::ActorId<MsgActor> msg) : msg(msg) {
|
||||
}
|
||||
void hangup() final {
|
||||
send_closure(msg, &MsgActor::msg);
|
||||
td::send_closure(msg, &MsgActor::msg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -340,10 +335,10 @@ class MasterActor final : public MsgActor {
|
||||
public:
|
||||
void loop() final {
|
||||
alive_ = true;
|
||||
slave = create_actor<Slave>("slave", static_cast<ActorId<MsgActor>>(actor_id(this)));
|
||||
slave = td::create_actor<Slave>("slave", static_cast<td::ActorId<MsgActor>>(actor_id(this)));
|
||||
stop();
|
||||
}
|
||||
ActorOwn<Slave> slave;
|
||||
td::ActorOwn<Slave> slave;
|
||||
|
||||
MasterActor() = default;
|
||||
MasterActor(const MasterActor &) = delete;
|
||||
@ -356,26 +351,25 @@ class MasterActor final : public MsgActor {
|
||||
void msg() final {
|
||||
CHECK(alive_ == 123456789);
|
||||
}
|
||||
uint64 alive_ = 123456789;
|
||||
td::uint64 alive_ = 123456789;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
TEST(Actors, call_after_destruct) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
Scheduler scheduler;
|
||||
td::Scheduler scheduler;
|
||||
scheduler.init(0, {create_queue()}, nullptr);
|
||||
{
|
||||
auto guard = scheduler.get_guard();
|
||||
create_actor<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:
|
||||
explicit LinkTokenSlave(ActorShared<> parent) : parent_(std::move(parent)) {
|
||||
explicit LinkTokenSlave(td::ActorShared<> parent) : parent_(std::move(parent)) {
|
||||
}
|
||||
void add(uint64 link_token) {
|
||||
void add(td::uint64 link_token) {
|
||||
CHECK(link_token == get_link_token());
|
||||
}
|
||||
void close() {
|
||||
@ -383,42 +377,43 @@ class LinkTokenSlave final : public Actor {
|
||||
}
|
||||
|
||||
private:
|
||||
ActorShared<> parent_;
|
||||
td::ActorShared<> parent_;
|
||||
};
|
||||
|
||||
class LinkTokenMasterActor final : public Actor {
|
||||
class LinkTokenMasterActor final : public td::Actor {
|
||||
public:
|
||||
explicit LinkTokenMasterActor(int cnt) : cnt_(cnt) {
|
||||
}
|
||||
void start_up() final {
|
||||
child_ = create_actor<LinkTokenSlave>("Slave", actor_shared(this, 123)).release();
|
||||
child_ = td::create_actor<LinkTokenSlave>("Slave", actor_shared(this, 123)).release();
|
||||
yield();
|
||||
}
|
||||
void loop() final {
|
||||
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) {
|
||||
case 0: {
|
||||
send_closure(ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token);
|
||||
td::send_closure(td::ActorShared<LinkTokenSlave>(child_, token), &LinkTokenSlave::add, token);
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cnt_ == 0) {
|
||||
send_closure(child_, &LinkTokenSlave::close);
|
||||
td::send_closure(child_, &LinkTokenSlave::close);
|
||||
} else {
|
||||
yield();
|
||||
}
|
||||
@ -426,18 +421,17 @@ class LinkTokenMasterActor final : public Actor {
|
||||
|
||||
void hangup_shared() final {
|
||||
CHECK(get_link_token() == 123);
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
stop();
|
||||
}
|
||||
|
||||
private:
|
||||
int cnt_;
|
||||
ActorId<LinkTokenSlave> child_;
|
||||
td::ActorId<LinkTokenSlave> child_;
|
||||
};
|
||||
|
||||
TEST(Actors, link_token) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(0);
|
||||
auto cnt = 100000;
|
||||
scheduler.create_actor_unsafe<LinkTokenMasterActor>(0, "A", cnt).release();
|
||||
@ -449,25 +443,25 @@ TEST(Actors, link_token) {
|
||||
|
||||
TEST(Actors, promise) {
|
||||
int value = -1;
|
||||
Promise<int> p1 = PromiseCreator::lambda([&](int x) { value = x; });
|
||||
p1.set_error(Status::Error("Test error"));
|
||||
td::Promise<int> p1 = td::PromiseCreator::lambda([&](int x) { value = x; });
|
||||
p1.set_error(td::Status::Error("Test error"));
|
||||
ASSERT_EQ(0, value);
|
||||
Promise<int32> p2 = PromiseCreator::lambda([&](Result<int32> x) { value = 1; });
|
||||
p2.set_error(Status::Error("Test error"));
|
||||
td::Promise<td::int32> p2 = td::PromiseCreator::lambda([&](td::Result<td::int32> x) { value = 1; });
|
||||
p2.set_error(td::Status::Error("Test error"));
|
||||
ASSERT_EQ(1, value);
|
||||
}
|
||||
|
||||
class LaterSlave final : public Actor {
|
||||
class LaterSlave final : public td::Actor {
|
||||
public:
|
||||
explicit LaterSlave(ActorShared<> parent) : parent_(std::move(parent)) {
|
||||
explicit LaterSlave(td::ActorShared<> parent) : parent_(std::move(parent)) {
|
||||
}
|
||||
|
||||
private:
|
||||
ActorShared<> parent_;
|
||||
td::ActorShared<> parent_;
|
||||
|
||||
void hangup() final {
|
||||
sb << "A";
|
||||
send_closure(actor_id(this), &LaterSlave::finish);
|
||||
td::send_closure(actor_id(this), &LaterSlave::finish);
|
||||
}
|
||||
void finish() {
|
||||
sb << "B";
|
||||
@ -475,12 +469,12 @@ class LaterSlave final : public Actor {
|
||||
}
|
||||
};
|
||||
|
||||
class LaterMasterActor final : public Actor {
|
||||
class LaterMasterActor final : public td::Actor {
|
||||
int cnt_ = 3;
|
||||
std::vector<ActorOwn<LaterSlave>> children_;
|
||||
td::vector<td::ActorOwn<LaterSlave>> children_;
|
||||
void start_up() final {
|
||||
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();
|
||||
}
|
||||
@ -489,16 +483,15 @@ class LaterMasterActor final : public Actor {
|
||||
}
|
||||
void hangup_shared() final {
|
||||
if (!--cnt_) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Actors, later) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
sb.clear();
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(0);
|
||||
scheduler.create_actor_unsafe<LaterMasterActor>(0, "A").release();
|
||||
scheduler.start();
|
||||
@ -508,38 +501,36 @@ TEST(Actors, later) {
|
||||
ASSERT_STREQ(sb.as_cslice().c_str(), "AAABBB");
|
||||
}
|
||||
|
||||
class MultiPromise2 final : public Actor {
|
||||
class MultiPromise2 final : public td::Actor {
|
||||
public:
|
||||
void start_up() final {
|
||||
auto promise = PromiseCreator::lambda([](Result<Unit> result) {
|
||||
auto promise = td::PromiseCreator::lambda([](td::Result<td::Unit> result) {
|
||||
result.ensure();
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
});
|
||||
|
||||
MultiPromiseActorSafe multi_promise{"MultiPromiseActor2"};
|
||||
td::MultiPromiseActorSafe multi_promise{"MultiPromiseActor2"};
|
||||
multi_promise.add_promise(std::move(promise));
|
||||
for (int i = 0; i < 10; i++) {
|
||||
create_actor<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:
|
||||
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());
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Actors, MultiPromise) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
sb.clear();
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(0);
|
||||
scheduler.create_actor_unsafe<MultiPromise1>(0, "A").release();
|
||||
scheduler.start();
|
||||
@ -548,22 +539,20 @@ TEST(Actors, MultiPromise) {
|
||||
scheduler.finish();
|
||||
}
|
||||
|
||||
class FastPromise final : public Actor {
|
||||
class FastPromise final : public td::Actor {
|
||||
public:
|
||||
void start_up() final {
|
||||
PromiseFuture<int> pf;
|
||||
td::PromiseFuture<int> pf;
|
||||
auto promise = pf.move_promise();
|
||||
auto future = pf.move_future();
|
||||
promise.set_value(123);
|
||||
CHECK(future.move_as_ok() == 123);
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Actors, FastPromise) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
sb.clear();
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(0);
|
||||
scheduler.create_actor_unsafe<FastPromise>(0, "A").release();
|
||||
scheduler.start();
|
||||
@ -572,20 +561,18 @@ TEST(Actors, FastPromise) {
|
||||
scheduler.finish();
|
||||
}
|
||||
|
||||
class StopInTeardown final : public Actor {
|
||||
class StopInTeardown final : public td::Actor {
|
||||
void loop() final {
|
||||
stop();
|
||||
}
|
||||
void tear_down() final {
|
||||
stop();
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Actors, stop_in_teardown) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
sb.clear();
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(0);
|
||||
scheduler.create_actor_unsafe<StopInTeardown>(0, "A").release();
|
||||
scheduler.start();
|
||||
@ -594,34 +581,33 @@ TEST(Actors, stop_in_teardown) {
|
||||
scheduler.finish();
|
||||
}
|
||||
|
||||
class AlwaysWaitForMailbox final : public Actor {
|
||||
class AlwaysWaitForMailbox final : public td::Actor {
|
||||
public:
|
||||
void start_up() final {
|
||||
always_wait_for_mailbox();
|
||||
create_actor<SleepActor>("Sleep", 0.1, PromiseCreator::lambda([actor_id = actor_id(this), ptr = this](Unit) {
|
||||
send_closure(actor_id, &AlwaysWaitForMailbox::g);
|
||||
send_closure(actor_id, &AlwaysWaitForMailbox::g);
|
||||
CHECK(!ptr->was_f_);
|
||||
}))
|
||||
td::create_actor<td::SleepActor>("Sleep", 0.1,
|
||||
td::PromiseCreator::lambda([actor_id = actor_id(this), ptr = this](td::Unit) {
|
||||
td::send_closure(actor_id, &AlwaysWaitForMailbox::g);
|
||||
td::send_closure(actor_id, &AlwaysWaitForMailbox::g);
|
||||
CHECK(!ptr->was_f_);
|
||||
}))
|
||||
.release();
|
||||
}
|
||||
|
||||
void f() {
|
||||
was_f_ = true;
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
void g() {
|
||||
send_closure(actor_id(this), &AlwaysWaitForMailbox::f);
|
||||
td::send_closure(actor_id(this), &AlwaysWaitForMailbox::f);
|
||||
}
|
||||
|
||||
private:
|
||||
Timeout timeout_;
|
||||
bool was_f_{false};
|
||||
};
|
||||
|
||||
TEST(Actors, always_wait_for_mailbox) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(0);
|
||||
scheduler.create_actor_unsafe<AlwaysWaitForMailbox>(0, "A").release();
|
||||
scheduler.start();
|
||||
@ -632,17 +618,16 @@ TEST(Actors, always_wait_for_mailbox) {
|
||||
|
||||
#if !TD_THREAD_UNSUPPORTED && !TD_EVENTFD_UNSUPPORTED
|
||||
TEST(Actors, send_from_other_threads) {
|
||||
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(ERROR));
|
||||
ConcurrentScheduler scheduler;
|
||||
td::ConcurrentScheduler scheduler;
|
||||
scheduler.init(1);
|
||||
int thread_n = 10;
|
||||
class Listener final : public Actor {
|
||||
class Listener final : public td::Actor {
|
||||
public:
|
||||
explicit Listener(int cnt) : cnt_(cnt) {
|
||||
}
|
||||
void dec() {
|
||||
if (--cnt_ == 0) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -652,11 +637,11 @@ TEST(Actors, send_from_other_threads) {
|
||||
|
||||
auto A = scheduler.create_actor_unsafe<Listener>(1, "A", thread_n).release();
|
||||
scheduler.start();
|
||||
std::vector<td::thread> threads(thread_n);
|
||||
td::vector<td::thread> threads(thread_n);
|
||||
for (auto &thread : threads) {
|
||||
thread = td::thread([&A, &scheduler] {
|
||||
auto guard = scheduler.get_send_guard();
|
||||
send_closure(A, &Listener::dec);
|
||||
td::send_closure(A, &Listener::dec);
|
||||
});
|
||||
}
|
||||
while (scheduler.run_main(10)) {
|
||||
@ -667,3 +652,45 @@ TEST(Actors, send_from_other_threads) {
|
||||
scheduler.finish();
|
||||
}
|
||||
#endif
|
||||
|
||||
class DelayedCall final : public td::Actor {
|
||||
public:
|
||||
void on_called(int *order) {
|
||||
CHECK(*order == 0);
|
||||
*order = 1;
|
||||
}
|
||||
};
|
||||
|
||||
class MultiPromiseSendClosureLaterTest final : public td::Actor {
|
||||
public:
|
||||
void start_up() final {
|
||||
delayed_call_ = td::create_actor<DelayedCall>("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();
|
||||
}
|
||||
|
@ -12,9 +12,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace td;
|
||||
|
||||
class PowerWorker final : public Actor {
|
||||
class PowerWorker final : public td::Actor {
|
||||
public:
|
||||
class Callback {
|
||||
public:
|
||||
@ -27,12 +25,12 @@ class PowerWorker final : public Actor {
|
||||
virtual void on_ready(int query, int res) = 0;
|
||||
virtual void on_closed() = 0;
|
||||
};
|
||||
void set_callback(unique_ptr<Callback> callback) {
|
||||
void set_callback(td::unique_ptr<Callback> callback) {
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
void task(uint32 x, uint32 p) {
|
||||
uint32 res = 1;
|
||||
for (uint32 i = 0; i < p; i++) {
|
||||
void task(td::uint32 x, td::uint32 p) {
|
||||
td::uint32 res = 1;
|
||||
for (td::uint32 i = 0; i < p; i++) {
|
||||
res *= x;
|
||||
}
|
||||
callback_->on_ready(x, res);
|
||||
@ -43,12 +41,12 @@ class PowerWorker final : public Actor {
|
||||
}
|
||||
|
||||
private:
|
||||
unique_ptr<Callback> callback_;
|
||||
td::unique_ptr<Callback> callback_;
|
||||
};
|
||||
|
||||
class Manager final : public Actor {
|
||||
class Manager final : public td::Actor {
|
||||
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))
|
||||
, ref_cnt_(static_cast<int>(workers_.size()))
|
||||
, left_query_(queries_n)
|
||||
@ -57,17 +55,17 @@ class Manager final : public Actor {
|
||||
|
||||
class Callback final : public PowerWorker::Callback {
|
||||
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 {
|
||||
send_closure(actor_id_, &Manager::on_ready, worker_id_, query, result);
|
||||
td::send_closure(actor_id_, &Manager::on_ready, worker_id_, query, result);
|
||||
}
|
||||
void on_closed() final {
|
||||
send_closure_later(actor_id_, &Manager::on_closed, worker_id_);
|
||||
td::send_closure_later(actor_id_, &Manager::on_closed, worker_id_);
|
||||
}
|
||||
|
||||
private:
|
||||
ActorId<Manager> actor_id_;
|
||||
td::ActorId<Manager> actor_id_;
|
||||
int worker_id_;
|
||||
};
|
||||
|
||||
@ -75,9 +73,9 @@ class Manager final : public Actor {
|
||||
int i = 0;
|
||||
for (auto &worker : workers_) {
|
||||
ref_cnt_++;
|
||||
send_closure_later(worker, &PowerWorker::set_callback, make_unique<Callback>(actor_id(this), i));
|
||||
td::send_closure_later(worker, &PowerWorker::set_callback, td::make_unique<Callback>(actor_id(this), i));
|
||||
i++;
|
||||
send_closure_later(worker, &PowerWorker::task, 3, query_size_);
|
||||
td::send_closure_later(worker, &PowerWorker::task, 3, query_size_);
|
||||
left_query_--;
|
||||
}
|
||||
}
|
||||
@ -85,10 +83,10 @@ class Manager final : public Actor {
|
||||
void on_ready(int worker_id, int query, int res) {
|
||||
ref_cnt_--;
|
||||
if (left_query_ == 0) {
|
||||
send_closure(workers_[worker_id], &PowerWorker::close);
|
||||
td::send_closure(workers_[worker_id], &PowerWorker::close);
|
||||
} else {
|
||||
ref_cnt_++;
|
||||
send_closure(workers_[worker_id], &PowerWorker::task, 3, query_size_);
|
||||
td::send_closure(workers_[worker_id], &PowerWorker::task, 3, query_size_);
|
||||
left_query_--;
|
||||
}
|
||||
}
|
||||
@ -96,23 +94,23 @@ class Manager final : public Actor {
|
||||
void on_closed(int worker_id) {
|
||||
ref_cnt_--;
|
||||
if (ref_cnt_ == 0) {
|
||||
Scheduler::instance()->finish();
|
||||
td::Scheduler::instance()->finish();
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<ActorId<PowerWorker>> workers_;
|
||||
td::vector<td::ActorId<PowerWorker>> workers_;
|
||||
int ref_cnt_;
|
||||
int left_query_;
|
||||
int query_size_;
|
||||
};
|
||||
|
||||
static void test_workers(int threads_n, int workers_n, int queries_n, int query_size) {
|
||||
ConcurrentScheduler sched;
|
||||
td::ConcurrentScheduler sched;
|
||||
sched.init(threads_n);
|
||||
|
||||
std::vector<ActorId<PowerWorker>> workers;
|
||||
td::vector<td::ActorId<PowerWorker>> workers;
|
||||
for (int i = 0; i < workers_n; i++) {
|
||||
int thread_id = threads_n ? i % (threads_n - 1) + 2 : 0;
|
||||
workers.push_back(sched.create_actor_unsafe<PowerWorker>(thread_id, PSLICE() << "worker" << i).release());
|
||||
|
@ -175,13 +175,20 @@ Status SqliteDb::set_user_version(int32 version) {
|
||||
return exec(PSLICE() << "PRAGMA user_version = " << version);
|
||||
}
|
||||
|
||||
Status SqliteDb::begin_transaction() {
|
||||
Status SqliteDb::begin_read_transaction() {
|
||||
if (raw_->on_begin()) {
|
||||
return exec("BEGIN");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status SqliteDb::begin_write_transaction() {
|
||||
if (raw_->on_begin()) {
|
||||
return exec("BEGIN IMMEDIATE");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status SqliteDb::commit_transaction() {
|
||||
TRY_RESULT(need_commit, raw_->on_commit());
|
||||
if (need_commit) {
|
||||
|
@ -46,7 +46,9 @@ class SqliteDb {
|
||||
Result<bool> has_table(Slice table);
|
||||
Result<string> get_pragma(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;
|
||||
|
||||
Result<int32> user_version();
|
||||
|
@ -51,8 +51,11 @@ class SqliteKeyValue {
|
||||
|
||||
SeqNo erase(Slice key);
|
||||
|
||||
Status begin_transaction() TD_WARN_UNUSED_RESULT {
|
||||
return db_.begin_transaction();
|
||||
Status begin_read_transaction() TD_WARN_UNUSED_RESULT {
|
||||
return db_.begin_read_transaction();
|
||||
}
|
||||
Status begin_write_transaction() TD_WARN_UNUSED_RESULT {
|
||||
return db_.begin_write_transaction();
|
||||
}
|
||||
Status commit_transaction() TD_WARN_UNUSED_RESULT {
|
||||
return db_.commit_transaction();
|
||||
|
@ -121,7 +121,7 @@ class SqliteKeyValueAsync final : public SqliteKeyValueAsyncInterface {
|
||||
wakeup_at_ = 0;
|
||||
cnt_ = 0;
|
||||
|
||||
kv_->begin_transaction().ensure();
|
||||
kv_->begin_write_transaction().ensure();
|
||||
for (auto &it : buffer_) {
|
||||
if (it.second) {
|
||||
kv_->set(it.first, it.second.value());
|
||||
|
@ -150,7 +150,9 @@ Slice get_operating_system_version() {
|
||||
}
|
||||
|
||||
var clientStrings = [
|
||||
{s:'Windows 10', r:/(Windows 10.0|Windows NT 10.0)/},
|
||||
{s:'Windows 11', r:/(Windows 11|Windows NT 11)/},
|
||||
// there is no way to distinguish Windows 10 from newer versions, so report it as just Windows.
|
||||
// {s:'Windows 10 or later', r:/(Windows 10|Windows NT 10)/},
|
||||
{s:'Windows 8.1', r:/(Windows 8.1|Windows NT 6.3)/},
|
||||
{s:'Windows 8', r:/(Windows 8|Windows NT 6.2)/},
|
||||
{s:'Windows 7', r:/(Windows 7|Windows NT 6.1)/},
|
||||
@ -242,7 +244,18 @@ Slice get_operating_system_version() {
|
||||
|
||||
if (major == 10) {
|
||||
if (is_server) {
|
||||
return os_version_info.dwBuildNumber >= 17623 ? "Windows Server 2019" : "Windows Server 2016";
|
||||
if (os_version_info.dwBuildNumber >= 20201) {
|
||||
// https://techcommunity.microsoft.com/t5/windows-server-insiders/announcing/m-p/1614436
|
||||
return "Windows Server 2022";
|
||||
}
|
||||
if (os_version_info.dwBuildNumber >= 17623) {
|
||||
// https://techcommunity.microsoft.com/t5/windows-server-insiders/announcing/m-p/173715
|
||||
return "Windows Server 2019";
|
||||
}
|
||||
return "Windows Server 2016";
|
||||
}
|
||||
if (os_version_info.dwBuildNumber >= 21900) { // build numbers between 21391 and 21999 aren't used
|
||||
return "Windows 11";
|
||||
}
|
||||
return "Windows 10";
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ TEST(EpochBaseMemoryReclamation, stress) {
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
LOG(ERROR) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe();
|
||||
LOG(INFO) << "Undeleted pointers: " << ebmr.to_delete_size_unsafe();
|
||||
//CHECK(static_cast<int>(ebmr.to_delete_size_unsafe()) <= threads_n * threads_n);
|
||||
for (int i = 0; i < threads_n; i++) {
|
||||
ebmr.get_locker(i).retire_sync();
|
||||
|
@ -50,7 +50,7 @@ TEST(HazardPointers, stress) {
|
||||
for (auto &thread : threads) {
|
||||
thread.join();
|
||||
}
|
||||
LOG(ERROR) << "Undeleted pointers: " << hazard_pointers.to_delete_size_unsafe();
|
||||
LOG(INFO) << "Undeleted pointers: " << hazard_pointers.to_delete_size_unsafe();
|
||||
CHECK(static_cast<int>(hazard_pointers.to_delete_size_unsafe()) <= threads_n * threads_n);
|
||||
for (int i = 0; i < threads_n; i++) {
|
||||
hazard_pointers.retire(i);
|
||||
|
@ -9,47 +9,45 @@
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
using namespace td;
|
||||
|
||||
TEST(Buffer, buffer_builder) {
|
||||
{
|
||||
BufferBuilder builder;
|
||||
td::BufferBuilder builder;
|
||||
builder.append("b");
|
||||
builder.prepend("a");
|
||||
builder.append("c");
|
||||
ASSERT_EQ(builder.extract().as_slice(), "abc");
|
||||
}
|
||||
{
|
||||
BufferBuilder builder{"hello", 0, 0};
|
||||
td::BufferBuilder builder{"hello", 0, 0};
|
||||
ASSERT_EQ(builder.extract().as_slice(), "hello");
|
||||
}
|
||||
{
|
||||
BufferBuilder builder{"hello", 1, 1};
|
||||
td::BufferBuilder builder{"hello", 1, 1};
|
||||
builder.prepend("A ");
|
||||
builder.append(" B");
|
||||
ASSERT_EQ(builder.extract().as_slice(), "A hello B");
|
||||
}
|
||||
{
|
||||
std::string str = rand_string('a', 'z', 10000);
|
||||
auto splitted_str = rand_split(str);
|
||||
auto str = td::rand_string('a', 'z', 10000);
|
||||
auto splitted_str = td::rand_split(str);
|
||||
|
||||
int l = Random::fast(0, static_cast<int32>(splitted_str.size() - 1));
|
||||
int l = td::Random::fast(0, static_cast<int>(splitted_str.size() - 1));
|
||||
int r = l;
|
||||
BufferBuilder builder(splitted_str[l], 123, 1000);
|
||||
while (l != 0 || r != static_cast<int32>(splitted_str.size()) - 1) {
|
||||
if (l == 0 || (Random::fast_bool() && r != static_cast<int32>(splitted_str.size() - 1))) {
|
||||
td::BufferBuilder builder(splitted_str[l], 123, 1000);
|
||||
while (l != 0 || r != static_cast<int>(splitted_str.size()) - 1) {
|
||||
if (l == 0 || (td::Random::fast_bool() && r != static_cast<int>(splitted_str.size() - 1))) {
|
||||
r++;
|
||||
if (Random::fast_bool()) {
|
||||
if (td::Random::fast_bool()) {
|
||||
builder.append(splitted_str[r]);
|
||||
} else {
|
||||
builder.append(BufferSlice(splitted_str[r]));
|
||||
builder.append(td::BufferSlice(splitted_str[r]));
|
||||
}
|
||||
} else {
|
||||
l--;
|
||||
if (Random::fast_bool()) {
|
||||
if (td::Random::fast_bool()) {
|
||||
builder.prepend(splitted_str[l]);
|
||||
} else {
|
||||
builder.prepend(BufferSlice(splitted_str[l]));
|
||||
builder.prepend(td::BufferSlice(splitted_str[l]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,17 +12,15 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace td;
|
||||
|
||||
static void decode_encode(string str, string result = "") {
|
||||
static void decode_encode(td::string str, td::string result = "") {
|
||||
auto str_copy = str;
|
||||
auto r_value = json_decode(str_copy);
|
||||
auto r_value = td::json_decode(str_copy);
|
||||
ASSERT_TRUE(r_value.is_ok());
|
||||
if (r_value.is_error()) {
|
||||
LOG(INFO) << r_value.error();
|
||||
return;
|
||||
}
|
||||
auto new_str = json_encode<string>(r_value.ok());
|
||||
auto new_str = td::json_encode<td::string>(r_value.ok());
|
||||
if (result.empty()) {
|
||||
result = str;
|
||||
}
|
||||
@ -31,18 +29,19 @@ static void decode_encode(string str, string result = "") {
|
||||
|
||||
TEST(JSON, array) {
|
||||
char tmp[1000];
|
||||
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||
JsonBuilder jb(std::move(sb));
|
||||
td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)});
|
||||
td::JsonBuilder jb(std::move(sb));
|
||||
jb.enter_value().enter_array() << "Hello" << -123;
|
||||
ASSERT_EQ(jb.string_builder().is_error(), false);
|
||||
auto encoded = jb.string_builder().as_cslice().str();
|
||||
ASSERT_EQ("[\"Hello\",-123]", encoded);
|
||||
decode_encode(encoded);
|
||||
}
|
||||
|
||||
TEST(JSON, object) {
|
||||
char tmp[1000];
|
||||
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||
JsonBuilder jb(std::move(sb));
|
||||
td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)});
|
||||
td::JsonBuilder jb(std::move(sb));
|
||||
auto c = jb.enter_object();
|
||||
c("key", "value");
|
||||
c("1", 2);
|
||||
@ -55,8 +54,8 @@ TEST(JSON, object) {
|
||||
|
||||
TEST(JSON, nested) {
|
||||
char tmp[1000];
|
||||
StringBuilder sb(MutableSlice{tmp, sizeof(tmp)});
|
||||
JsonBuilder jb(std::move(sb));
|
||||
td::StringBuilder sb(td::MutableSlice{tmp, sizeof(tmp)});
|
||||
td::JsonBuilder jb(std::move(sb));
|
||||
{
|
||||
auto a = jb.enter_array();
|
||||
a << 1;
|
||||
|
@ -18,11 +18,9 @@
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
using namespace td;
|
||||
|
||||
#if TD_HAVE_OPENSSL
|
||||
static bool is_prime(uint64 x) {
|
||||
for (uint64 d = 2; d < x && d * d <= x; d++) {
|
||||
static bool is_prime(td::uint64 x) {
|
||||
for (td::uint64 d = 2; d < x && d * d <= x; d++) {
|
||||
if (x % d == 0) {
|
||||
return false;
|
||||
}
|
||||
@ -30,8 +28,8 @@ static bool is_prime(uint64 x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static std::vector<uint64> gen_primes(uint64 L, uint64 R, int limit = 0) {
|
||||
std::vector<uint64> res;
|
||||
static td::vector<td::uint64> gen_primes(td::uint64 L, td::uint64 R, int limit = 0) {
|
||||
td::vector<td::uint64> res;
|
||||
for (auto x = L; x <= R && (limit <= 0 || res.size() < static_cast<std::size_t>(limit)); x++) {
|
||||
if (is_prime(x)) {
|
||||
res.push_back(x);
|
||||
@ -40,21 +38,23 @@ static std::vector<uint64> gen_primes(uint64 L, uint64 R, int limit = 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static std::vector<uint64> gen_primes() {
|
||||
std::vector<uint64> result;
|
||||
append(result, gen_primes(1, 100));
|
||||
append(result, gen_primes((1ull << 31) - 500000, std::numeric_limits<uint64>::max(), 5));
|
||||
append(result, gen_primes((1ull << 32) - 500000, std::numeric_limits<uint64>::max(), 5));
|
||||
append(result, gen_primes((1ull << 39) - 500000, std::numeric_limits<uint64>::max(), 1));
|
||||
static td::vector<td::uint64> gen_primes() {
|
||||
td::vector<td::uint64> result;
|
||||
td::append(result, gen_primes(1, 100));
|
||||
td::append(result, gen_primes((1ull << 31) - 500000, std::numeric_limits<td::uint64>::max(), 5));
|
||||
td::append(result, gen_primes((1ull << 32) - 500000, std::numeric_limits<td::uint64>::max(), 5));
|
||||
td::append(result, gen_primes((1ull << 39) - 500000, std::numeric_limits<td::uint64>::max(), 1));
|
||||
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) {
|
||||
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();
|
||||
for (auto q : primes) {
|
||||
for (auto p : primes) {
|
||||
@ -68,21 +68,21 @@ static std::vector<PqQuery> gen_pq_queries() {
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_pq(uint64 first, uint64 second) {
|
||||
BigNum p = BigNum::from_decimal(PSLICE() << first).move_as_ok();
|
||||
BigNum q = BigNum::from_decimal(PSLICE() << second).move_as_ok();
|
||||
static void test_pq(td::uint64 first, td::uint64 second) {
|
||||
td::BigNum p = td::BigNum::from_decimal(PSLICE() << first).move_as_ok();
|
||||
td::BigNum q = td::BigNum::from_decimal(PSLICE() << second).move_as_ok();
|
||||
|
||||
BigNum pq;
|
||||
BigNumContext context;
|
||||
BigNum::mul(pq, p, q, context);
|
||||
std::string pq_str = pq.to_binary();
|
||||
td::BigNum pq;
|
||||
td::BigNumContext context;
|
||||
td::BigNum::mul(pq, p, q, context);
|
||||
td::string pq_str = pq.to_binary();
|
||||
|
||||
std::string p_str, q_str;
|
||||
td::string p_str, q_str;
|
||||
int err = td::pq_factorize(pq_str, &p_str, &q_str);
|
||||
LOG_CHECK(err == 0) << first << " * " << second;
|
||||
|
||||
BigNum p_res = BigNum::from_binary(p_str);
|
||||
BigNum q_res = BigNum::from_binary(q_str);
|
||||
td::BigNum p_res = td::BigNum::from_binary(p_str);
|
||||
td::BigNum q_res = td::BigNum::from_binary(q_str);
|
||||
|
||||
LOG_CHECK(p_str == p.to_binary()) << td::tag("got", p_res.to_decimal()) << td::tag("expected", first);
|
||||
LOG_CHECK(q_str == q.to_binary()) << td::tag("got", q_res.to_decimal()) << td::tag("expected", second);
|
||||
|
Loading…
x
Reference in New Issue
Block a user