ContactsManager partial locking when cleaning

This commit is contained in:
Andrea Cavalli 2020-08-02 00:24:48 +02:00
parent ee676d0a52
commit 35fe9a1409
2 changed files with 212 additions and 116 deletions

View File

@ -282,7 +282,7 @@ class GetWebAuthorizationsQuery : public Td::ResultHandler {
results->websites_.push_back(make_tl_object<td_api::connectedWebsite>( results->websites_.push_back(make_tl_object<td_api::connectedWebsite>(
authorization->hash_, authorization->domain_, authorization->hash_, authorization->domain_,
td->contacts_manager_->get_user_id_object(bot_user_id, "GetWebAuthorizationsQuery"), authorization->browser_, td->contacts_manager_->get_user_id_object_internal(bot_user_id, "GetWebAuthorizationsQuery"), authorization->browser_,
authorization->platform_, authorization->date_created_, authorization->date_active_, authorization->ip_, authorization->platform_, authorization->date_created_, authorization->date_active_, authorization->ip_,
authorization->region_)); authorization->region_));
} }
@ -2760,17 +2760,17 @@ tl_object_ptr<td_api::ChatStatistics> ContactsManager::convert_megagroup_stats(
auto top_senders = transform(std::move(obj->top_posters_), [this](auto &&top_poster) { auto top_senders = transform(std::move(obj->top_posters_), [this](auto &&top_poster) {
return td_api::make_object<td_api::chatStatisticsMessageSenderInfo>( return td_api::make_object<td_api::chatStatisticsMessageSenderInfo>(
this->get_user_id_object(UserId(top_poster->user_id_), "get_top_senders"), top_poster->messages_, this->get_user_id_object_internal(UserId(top_poster->user_id_), "get_top_senders"), top_poster->messages_,
top_poster->avg_chars_); top_poster->avg_chars_);
}); });
auto top_administrators = transform(std::move(obj->top_admins_), [this](auto &&top_admin) { auto top_administrators = transform(std::move(obj->top_admins_), [this](auto &&top_admin) {
return td_api::make_object<td_api::chatStatisticsAdministratorActionsInfo>( return td_api::make_object<td_api::chatStatisticsAdministratorActionsInfo>(
this->get_user_id_object(UserId(top_admin->user_id_), "get_top_administrators"), top_admin->deleted_, this->get_user_id_object_internal(UserId(top_admin->user_id_), "get_top_administrators"), top_admin->deleted_,
top_admin->kicked_, top_admin->banned_); top_admin->kicked_, top_admin->banned_);
}); });
auto top_inviters = transform(std::move(obj->top_inviters_), [this](auto &&top_inviter) { auto top_inviters = transform(std::move(obj->top_inviters_), [this](auto &&top_inviter) {
return td_api::make_object<td_api::chatStatisticsInviterInfo>( return td_api::make_object<td_api::chatStatisticsInviterInfo>(
this->get_user_id_object(UserId(top_inviter->user_id_), "get_top_inviters"), top_inviter->invitations_); this->get_user_id_object_internal(UserId(top_inviter->user_id_), "get_top_inviters"), top_inviter->invitations_);
}); });
return make_tl_object<td_api::chatStatisticsSupergroup>( return make_tl_object<td_api::chatStatisticsSupergroup>(
@ -4689,7 +4689,7 @@ tl_object_ptr<td_api::users> ContactsManager::get_blocked_users_object(int64 ran
if (it == found_blocked_users_.end()) { if (it == found_blocked_users_.end()) {
return nullptr; return nullptr;
} }
auto result = get_users_object(it->second.first, it->second.second); auto result = get_users_object_internal(it->second.first, it->second.second);
found_blocked_users_.erase(it); found_blocked_users_.erase(it);
return result; return result;
} }
@ -4957,7 +4957,7 @@ void ContactsManager::on_load_imported_contacts_finished() {
LOG(INFO) << "Finished to load " << all_imported_contacts_.size() << " imported contacts"; LOG(INFO) << "Finished to load " << all_imported_contacts_.size() << " imported contacts";
for (const auto &contact : all_imported_contacts_) { for (const auto &contact : all_imported_contacts_) {
get_user_id_object(contact.get_user_id(), "on_load_imported_contacts_finished"); // to ensure updateUser get_user_id_object_internal(contact.get_user_id(), "on_load_imported_contacts_finished"); // to ensure updateUser
} }
if (need_clear_imported_contacts_) { if (need_clear_imported_contacts_) {
@ -6873,7 +6873,7 @@ void ContactsManager::on_imported_contacts(int64 random_id, vector<UserId> impor
std::unordered_map<size_t, int32> unique_id_to_unimported_contact_invites; std::unordered_map<size_t, int32> unique_id_to_unimported_contact_invites;
for (size_t i = 0; i < add_size; i++) { for (size_t i = 0; i < add_size; i++) {
auto unique_id = imported_contacts_pos_[i]; auto unique_id = imported_contacts_pos_[i];
get_user_id_object(imported_contact_user_ids[i], "on_imported_contacts"); // to ensure updateUser get_user_id_object_internal(imported_contact_user_ids[i], "on_imported_contacts"); // to ensure updateUser
all_imported_contacts_[unique_id].set_user_id(imported_contact_user_ids[i]); all_imported_contacts_[unique_id].set_user_id(imported_contact_user_ids[i]);
unique_id_to_unimported_contact_invites[unique_id] = unimported_contact_invites[i]; unique_id_to_unimported_contact_invites[unique_id] = unimported_contact_invites[i];
} }
@ -8144,7 +8144,7 @@ void ContactsManager::on_binlog_secret_chat_event(BinlogEvent &&event) {
log_event_parse(log_event, event.data_).ensure(); log_event_parse(log_event, event.data_).ensure();
auto secret_chat_id = log_event.secret_chat_id; auto secret_chat_id = log_event.secret_chat_id;
if (have_secret_chat(secret_chat_id)) { if (have_secret_chat_internal(secret_chat_id)) {
LOG(ERROR) << "Skip adding already added " << secret_chat_id; LOG(ERROR) << "Skip adding already added " << secret_chat_id;
binlog_erase(G()->td_db()->get_binlog(), event.id_); binlog_erase(G()->td_db()->get_binlog(), event.id_);
return; return;
@ -9012,7 +9012,7 @@ void ContactsManager::update_user_full(UserFull *user_full, UserId user_id, bool
CHECK(u == nullptr || u->is_update_user_sent); CHECK(u == nullptr || u->is_update_user_sent);
} }
send_closure(G()->td(), &Td::send_update, send_closure(G()->td(), &Td::send_update,
make_tl_object<td_api::updateUserFullInfo>(get_user_id_object(user_id, "updateUserFullInfo"), make_tl_object<td_api::updateUserFullInfo>(get_user_id_object_internal(user_id, "updateUserFullInfo"),
get_user_full_info_object(user_id, user_full))); get_user_full_info_object(user_id, user_full)));
user_full->need_send_update = false; user_full->need_send_update = false;
} }
@ -9052,7 +9052,7 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool
} }
send_closure( send_closure(
G()->td(), &Td::send_update, G()->td(), &Td::send_update,
make_tl_object<td_api::updateBasicGroupFullInfo>(get_basic_group_id_object(chat_id, "update_chat_full"), make_tl_object<td_api::updateBasicGroupFullInfo>(get_basic_group_id_object_internal(chat_id, "update_chat_full"),
get_basic_group_full_info_object(chat_full))); get_basic_group_full_info_object(chat_full)));
chat_full->need_send_update = false; chat_full->need_send_update = false;
} }
@ -9103,7 +9103,7 @@ void ContactsManager::update_channel_full(ChannelFull *channel_full, ChannelId c
} }
send_closure( send_closure(
G()->td(), &Td::send_update, G()->td(), &Td::send_update,
make_tl_object<td_api::updateSupergroupFullInfo>(get_supergroup_id_object(channel_id, "update_channel_full"), make_tl_object<td_api::updateSupergroupFullInfo>(get_supergroup_id_object_internal(channel_id, "update_channel_full"),
get_supergroup_full_info_object(channel_full))); get_supergroup_full_info_object(channel_full)));
channel_full->need_send_update = false; channel_full->need_send_update = false;
} }
@ -9697,16 +9697,19 @@ void ContactsManager::on_update_user_photo(UserId user_id, tl_object_ptr<telegra
void ContactsManager::on_update_user_photo(User *u, UserId user_id, void ContactsManager::on_update_user_photo(User *u, UserId user_id,
tl_object_ptr<telegram_api::UserProfilePhoto> &&photo, const char *source) { tl_object_ptr<telegram_api::UserProfilePhoto> &&photo, const char *source) {
if (td_->auth_manager_->is_bot() && !G()->parameters().use_file_db && !u->is_photo_inited) { if (td_->auth_manager_->is_bot() && !G()->parameters().use_file_db && !u->is_photo_inited) {
auto &old_photo = pending_user_photos_[user_id]; auto find_old_photo = pending_user_photos_.find(user_id);
if (!LOG_IS_STRIPPED(ERROR) && to_string(old_photo) == to_string(photo)) { if (find_old_photo != pending_user_photos_.end()) {
auto &old_photo = find_old_photo->second;
if (!LOG_IS_STRIPPED(ERROR) && to_string(old_photo) == to_string(photo)) {
return;
}
bool is_empty = photo == nullptr || photo->get_id() == telegram_api::userProfilePhotoEmpty::ID;
old_photo = std::move(photo);
drop_user_photos(user_id, is_empty, true, "on_update_user_photo");
return; return;
} }
bool is_empty = photo == nullptr || photo->get_id() == telegram_api::userProfilePhotoEmpty::ID;
old_photo = std::move(photo);
drop_user_photos(user_id, is_empty, true, "on_update_user_photo");
return;
} }
do_update_user_photo(u, user_id, std::move(photo), source); do_update_user_photo(u, user_id, std::move(photo), source);
@ -10441,8 +10444,8 @@ tl_object_ptr<td_api::chatMember> ContactsManager::get_chat_member_object(
const DialogParticipant &dialog_participant) const { const DialogParticipant &dialog_participant) const {
UserId participant_user_id = dialog_participant.user_id; UserId participant_user_id = dialog_participant.user_id;
return td_api::make_object<td_api::chatMember>( return td_api::make_object<td_api::chatMember>(
get_user_id_object(participant_user_id, "chatMember.user_id"), get_user_id_object_internal(participant_user_id, "chatMember.user_id"),
get_user_id_object(dialog_participant.inviter_user_id, "chatMember.inviter_user_id"), get_user_id_object_internal(dialog_participant.inviter_user_id, "chatMember.inviter_user_id"),
dialog_participant.joined_date, dialog_participant.status.get_chat_member_status_object(), dialog_participant.joined_date, dialog_participant.status.get_chat_member_status_object(),
get_bot_info_object(participant_user_id)); get_bot_info_object(participant_user_id));
} }
@ -12981,6 +12984,7 @@ bool ContactsManager::get_channel_full(ChannelId channel_id, bool force, Promise
} }
void ContactsManager::reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source) { void ContactsManager::reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
send_get_channel_full_query(get_channel_full(channel_id, "reload_channel_full"), channel_id, std::move(promise), send_get_channel_full_query(get_channel_full(channel_id, "reload_channel_full"), channel_id, std::move(promise),
source); source);
} }
@ -13015,6 +13019,11 @@ void ContactsManager::send_get_channel_full_query(ChannelFull *channel_full, Cha
} }
bool ContactsManager::have_secret_chat(SecretChatId secret_chat_id) const { bool ContactsManager::have_secret_chat(SecretChatId secret_chat_id) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return have_secret_chat_internal(secret_chat_id);
}
bool ContactsManager::have_secret_chat_internal(SecretChatId secret_chat_id) const {
return secret_chats_.count(secret_chat_id) > 0; return secret_chats_.count(secret_chat_id) > 0;
} }
@ -13045,11 +13054,12 @@ ContactsManager::SecretChat *ContactsManager::get_secret_chat(SecretChatId secre
bool ContactsManager::get_secret_chat(SecretChatId secret_chat_id, bool force, Promise<Unit> &&promise) { bool ContactsManager::get_secret_chat(SecretChatId secret_chat_id, bool force, Promise<Unit> &&promise) {
if (!secret_chat_id.is_valid()) { if (!secret_chat_id.is_valid()) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
promise.set_error(Status::Error(6, "Invalid secret chat identifier")); promise.set_error(Status::Error(6, "Invalid secret chat identifier"));
return false; return false;
} }
if (!have_secret_chat(secret_chat_id)) { if (!have_secret_chat_internal(secret_chat_id)) {
if (!force && G()->parameters().use_chat_info_db) { if (!force && G()->parameters().use_chat_info_db) {
send_closure_later(actor_id(this), &ContactsManager::load_secret_chat_from_database, nullptr, secret_chat_id, send_closure_later(actor_id(this), &ContactsManager::load_secret_chat_from_database, nullptr, secret_chat_id,
std::move(promise)); std::move(promise));
@ -13067,6 +13077,7 @@ bool ContactsManager::get_secret_chat(SecretChatId secret_chat_id, bool force, P
void ContactsManager::on_update_secret_chat(SecretChatId secret_chat_id, int64 access_hash, UserId user_id, void ContactsManager::on_update_secret_chat(SecretChatId secret_chat_id, int64 access_hash, UserId user_id,
SecretChatState state, bool is_outbound, int32 ttl, int32 date, SecretChatState state, bool is_outbound, int32 ttl, int32 date,
string key_hash, int32 layer, FolderId initial_folder_id) { string key_hash, int32 layer, FolderId initial_folder_id) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
LOG(INFO) << "Update " << secret_chat_id << " with " << user_id << " and access_hash " << access_hash; LOG(INFO) << "Update " << secret_chat_id << " with " << user_id << " and access_hash " << access_hash;
auto *secret_chat = add_secret_chat(secret_chat_id); auto *secret_chat = add_secret_chat(secret_chat_id);
if (access_hash != secret_chat->access_hash) { if (access_hash != secret_chat->access_hash) {
@ -13119,6 +13130,12 @@ void ContactsManager::on_update_secret_chat(SecretChatId secret_chat_id, int64 a
std::pair<int32, vector<UserId>> ContactsManager::search_among_users(const vector<UserId> &user_ids, std::pair<int32, vector<UserId>> ContactsManager::search_among_users(const vector<UserId> &user_ids,
const string &query, int32 limit) { const string &query, int32 limit) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return search_among_users_internal(user_ids, query, limit);
}
std::pair<int32, vector<UserId>> ContactsManager::search_among_users_internal(const vector<UserId> &user_ids,
const string &query, int32 limit) {
Hints hints; // TODO cache Hints Hints hints; // TODO cache Hints
for (auto user_id : user_ids) { for (auto user_id : user_ids) {
@ -13137,6 +13154,7 @@ std::pair<int32, vector<UserId>> ContactsManager::search_among_users(const vecto
DialogParticipant ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, bool force, DialogParticipant ContactsManager::get_chat_participant(ChatId chat_id, UserId user_id, bool force,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
LOG(INFO) << "Trying to get " << user_id << " as member of " << chat_id; LOG(INFO) << "Trying to get " << user_id << " as member of " << chat_id;
if (force) { if (force) {
promise.set_value(Unit()); promise.set_value(Unit());
@ -13158,6 +13176,7 @@ std::pair<int32, vector<DialogParticipant>> ContactsManager::search_chat_partici
DialogParticipantsFilter filter, DialogParticipantsFilter filter,
bool force, bool force,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
if (limit < 0) { if (limit < 0) {
promise.set_error(Status::Error(3, "Parameter limit must be non-negative")); promise.set_error(Status::Error(3, "Parameter limit must be non-negative"));
return {}; return {};
@ -13203,12 +13222,13 @@ std::pair<int32, vector<DialogParticipant>> ContactsManager::search_chat_partici
} }
int32 total_count; int32 total_count;
std::tie(total_count, user_ids) = search_among_users(user_ids, query, limit); std::tie(total_count, user_ids) = search_among_users_internal(user_ids, query, limit);
return {total_count, transform(user_ids, [&](UserId user_id) { return *get_chat_participant(chat_full, user_id); })}; return {total_count, transform(user_ids, [&](UserId user_id) { return *get_chat_participant(chat_full, user_id); })};
} }
DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, UserId user_id, int64 &random_id, DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id, UserId user_id, int64 &random_id,
bool force, Promise<Unit> &&promise) { bool force, Promise<Unit> &&promise) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
LOG(INFO) << "Trying to get " << user_id << " as member of " << channel_id << " with random_id " << random_id; LOG(INFO) << "Trying to get " << user_id << " as member of " << channel_id << " with random_id " << random_id;
if (random_id != 0) { if (random_id != 0) {
// request has already been sent before // request has already been sent before
@ -13271,6 +13291,7 @@ DialogParticipant ContactsManager::get_channel_participant(ChannelId channel_id,
std::pair<int32, vector<DialogParticipant>> ContactsManager::get_channel_participants( std::pair<int32, vector<DialogParticipant>> ContactsManager::get_channel_participants(
ChannelId channel_id, const tl_object_ptr<td_api::SupergroupMembersFilter> &filter, const string &additional_query, ChannelId channel_id, const tl_object_ptr<td_api::SupergroupMembersFilter> &filter, const string &additional_query,
int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool force, Promise<Unit> &&promise) { int32 offset, int32 limit, int32 additional_limit, int64 &random_id, bool force, Promise<Unit> &&promise) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
if (random_id != 0) { if (random_id != 0) {
// request has already been sent before // request has already been sent before
auto it = received_channel_participants_.find(random_id); auto it = received_channel_participants_.find(random_id);
@ -13284,7 +13305,7 @@ std::pair<int32, vector<DialogParticipant>> ContactsManager::get_channel_partici
} }
auto user_ids = transform(result.second, [](const auto &participant) { return participant.user_id; }); auto user_ids = transform(result.second, [](const auto &participant) { return participant.user_id; });
std::pair<int32, vector<UserId>> result_user_ids = search_among_users(user_ids, additional_query, additional_limit); std::pair<int32, vector<UserId>> result_user_ids = search_among_users_internal(user_ids, additional_query, additional_limit);
result.first = result_user_ids.first; result.first = result_user_ids.first;
std::unordered_set<UserId, UserIdHash> result_user_ids_set(result_user_ids.second.begin(), std::unordered_set<UserId, UserIdHash> result_user_ids_set(result_user_ids.second.begin(),
@ -13350,6 +13371,7 @@ void ContactsManager::send_get_channel_participants_query(ChannelId channel_id,
vector<DialogAdministrator> ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries, vector<DialogAdministrator> ContactsManager::get_dialog_administrators(DialogId dialog_id, int left_tries,
Promise<Unit> &&promise) { Promise<Unit> &&promise) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
auto it = dialog_administrators_.find(dialog_id); auto it = dialog_administrators_.find(dialog_id);
if (it != dialog_administrators_.end()) { if (it != dialog_administrators_.end()) {
promise.set_value(Unit()); promise.set_value(Unit());
@ -13954,6 +13976,11 @@ td_api::object_ptr<td_api::updateUser> ContactsManager::get_update_unknown_user_
} }
int32 ContactsManager::get_user_id_object(UserId user_id, const char *source) const { int32 ContactsManager::get_user_id_object(UserId user_id, const char *source) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_user_id_object_internal(user_id, source);
}
int32 ContactsManager::get_user_id_object_internal(UserId user_id, const char *source) const {
if (user_id.is_valid() && get_user(user_id) == nullptr && unknown_users_.count(user_id) == 0) { if (user_id.is_valid() && get_user(user_id) == nullptr && unknown_users_.count(user_id) == 0) {
LOG(ERROR) << "Have no info about " << user_id << " from " << source; LOG(ERROR) << "Have no info about " << user_id << " from " << source;
unknown_users_.insert(user_id); unknown_users_.insert(user_id);
@ -13963,6 +13990,7 @@ int32 ContactsManager::get_user_id_object(UserId user_id, const char *source) co
} }
tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id) const { tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_user_object(user_id, get_user(user_id)); return get_user_object(user_id, get_user(user_id));
} }
@ -13988,18 +14016,30 @@ tl_object_ptr<td_api::user> ContactsManager::get_user_object(UserId user_id, con
} }
vector<int32> ContactsManager::get_user_ids_object(const vector<UserId> &user_ids, const char *source) const { vector<int32> ContactsManager::get_user_ids_object(const vector<UserId> &user_ids, const char *source) const {
return transform(user_ids, [this, source](UserId user_id) { return get_user_id_object(user_id, source); }); std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_user_ids_object_internal(user_ids, source);
}
vector<int32> ContactsManager::get_user_ids_object_internal(const vector<UserId> &user_ids, const char *source) const {
return transform(user_ids, [this, source](UserId user_id) { return get_user_id_object_internal(user_id, source); });
} }
tl_object_ptr<td_api::users> ContactsManager::get_users_object(int32 total_count, tl_object_ptr<td_api::users> ContactsManager::get_users_object(int32 total_count,
const vector<UserId> &user_ids) const { const vector<UserId> &user_ids) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_users_object_internal(total_count, user_ids);
}
tl_object_ptr<td_api::users> ContactsManager::get_users_object_internal(int32 total_count,
const vector<UserId> &user_ids) const {
if (total_count == -1) { if (total_count == -1) {
total_count = narrow_cast<int32>(user_ids.size()); total_count = narrow_cast<int32>(user_ids.size());
} }
return td_api::make_object<td_api::users>(total_count, get_user_ids_object(user_ids, "get_users_object")); return td_api::make_object<td_api::users>(total_count, get_user_ids_object_internal(user_ids, "get_users_object"));
} }
tl_object_ptr<td_api::userFullInfo> ContactsManager::get_user_full_info_object(UserId user_id) const { tl_object_ptr<td_api::userFullInfo> ContactsManager::get_user_full_info_object(UserId user_id) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_user_full_info_object(user_id, get_user_full(user_id)); return get_user_full_info_object(user_id, get_user_full(user_id));
} }
@ -14020,6 +14060,11 @@ td_api::object_ptr<td_api::updateBasicGroup> ContactsManager::get_update_unknown
} }
int32 ContactsManager::get_basic_group_id_object(ChatId chat_id, const char *source) const { int32 ContactsManager::get_basic_group_id_object(ChatId chat_id, const char *source) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_basic_group_id_object_internal(chat_id, source);
}
int32 ContactsManager::get_basic_group_id_object_internal(ChatId chat_id, const char *source) const {
if (chat_id.is_valid() && get_chat(chat_id) == nullptr && unknown_chats_.count(chat_id) == 0) { if (chat_id.is_valid() && get_chat(chat_id) == nullptr && unknown_chats_.count(chat_id) == 0) {
LOG(ERROR) << "Have no info about " << chat_id << " from " << source; LOG(ERROR) << "Have no info about " << chat_id << " from " << source;
unknown_chats_.insert(chat_id); unknown_chats_.insert(chat_id);
@ -14029,6 +14074,7 @@ int32 ContactsManager::get_basic_group_id_object(ChatId chat_id, const char *sou
} }
tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object(ChatId chat_id) { tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object(ChatId chat_id) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_basic_group_object(chat_id, get_chat(chat_id)); return get_basic_group_object(chat_id, get_chat(chat_id));
} }
@ -14045,10 +14091,11 @@ tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object(ChatId
tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object_const(ChatId chat_id, const Chat *c) const { tl_object_ptr<td_api::basicGroup> ContactsManager::get_basic_group_object_const(ChatId chat_id, const Chat *c) const {
return make_tl_object<td_api::basicGroup>( return make_tl_object<td_api::basicGroup>(
chat_id.get(), c->participant_count, get_chat_status(c).get_chat_member_status_object(), c->is_active, chat_id.get(), c->participant_count, get_chat_status(c).get_chat_member_status_object(), c->is_active,
get_supergroup_id_object(c->migrated_to_channel_id, "get_basic_group_object")); get_supergroup_id_object_internal(c->migrated_to_channel_id, "get_basic_group_object"));
} }
tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_info_object(ChatId chat_id) const { tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_info_object(ChatId chat_id) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_basic_group_full_info_object(get_chat_full(chat_id)); return get_basic_group_full_info_object(get_chat_full(chat_id));
} }
@ -14057,7 +14104,7 @@ tl_object_ptr<td_api::basicGroupFullInfo> ContactsManager::get_basic_group_full_
CHECK(chat_full != nullptr); CHECK(chat_full != nullptr);
return make_tl_object<td_api::basicGroupFullInfo>( return make_tl_object<td_api::basicGroupFullInfo>(
get_chat_photo_object(td_->file_manager_.get(), chat_full->photo), chat_full->description, get_chat_photo_object(td_->file_manager_.get(), chat_full->photo), chat_full->description,
get_user_id_object(chat_full->creator_user_id, "basicGroupFullInfo"), get_user_id_object_internal(chat_full->creator_user_id, "basicGroupFullInfo"),
transform(chat_full->participants, transform(chat_full->participants,
[this](const DialogParticipant &chat_participant) { return get_chat_member_object(chat_participant); }), [this](const DialogParticipant &chat_participant) { return get_chat_member_object(chat_participant); }),
chat_full->invite_link); chat_full->invite_link);
@ -14071,6 +14118,11 @@ td_api::object_ptr<td_api::updateSupergroup> ContactsManager::get_update_unknown
} }
int32 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char *source) const { int32 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char *source) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_supergroup_id_object_internal(channel_id, source);
}
int32 ContactsManager::get_supergroup_id_object_internal(ChannelId channel_id, const char *source) const {
if (channel_id.is_valid() && get_channel(channel_id) == nullptr && unknown_channels_.count(channel_id) == 0) { if (channel_id.is_valid() && get_channel(channel_id) == nullptr && unknown_channels_.count(channel_id) == 0) {
LOG(ERROR) << "Have no info about " << channel_id << " received from " << source; LOG(ERROR) << "Have no info about " << channel_id << " received from " << source;
unknown_channels_.insert(channel_id); unknown_channels_.insert(channel_id);
@ -14080,6 +14132,7 @@ int32 ContactsManager::get_supergroup_id_object(ChannelId channel_id, const char
} }
tl_object_ptr<td_api::supergroup> ContactsManager::get_supergroup_object(ChannelId channel_id) const { tl_object_ptr<td_api::supergroup> ContactsManager::get_supergroup_object(ChannelId channel_id) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_supergroup_object(channel_id, get_channel(channel_id)); return get_supergroup_object(channel_id, get_channel(channel_id));
} }
@ -14094,6 +14147,7 @@ tl_object_ptr<td_api::supergroup> ContactsManager::get_supergroup_object(Channel
} }
tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const { tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_info_object(ChannelId channel_id) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
return get_supergroup_full_info_object(get_channel_full(channel_id)); return get_supergroup_full_info_object(get_channel_full(channel_id));
} }
@ -14114,7 +14168,7 @@ tl_object_ptr<td_api::supergroupFullInfo> ContactsManager::get_supergroup_full_i
channel_full->can_set_sticker_set, channel_full->can_set_location, channel_full->stats_dc_id.is_exact(), channel_full->can_set_sticker_set, channel_full->can_set_location, channel_full->stats_dc_id.is_exact(),
channel_full->is_all_history_available, channel_full->sticker_set_id.get(), channel_full->is_all_history_available, channel_full->sticker_set_id.get(),
channel_full->location.get_chat_location_object(), channel_full->invite_link, channel_full->location.get_chat_location_object(), channel_full->invite_link,
get_basic_group_id_object(channel_full->migrated_from_chat_id, "get_supergroup_full_info_object"), get_basic_group_id_object_internal(channel_full->migrated_from_chat_id, "get_supergroup_full_info_object"),
channel_full->migrated_from_max_message_id.get()); channel_full->migrated_from_max_message_id.get());
} }
@ -14165,7 +14219,7 @@ tl_object_ptr<td_api::secretChat> ContactsManager::get_secret_chat_object(Secret
tl_object_ptr<td_api::secretChat> ContactsManager::get_secret_chat_object_const(SecretChatId secret_chat_id, tl_object_ptr<td_api::secretChat> ContactsManager::get_secret_chat_object_const(SecretChatId secret_chat_id,
const SecretChat *secret_chat) const { const SecretChat *secret_chat) const {
return td_api::make_object<td_api::secretChat>( return td_api::make_object<td_api::secretChat>(
secret_chat_id.get(), get_user_id_object(secret_chat->user_id, "secretChat"), secret_chat_id.get(), get_user_id_object_internal(secret_chat->user_id, "secretChat"),
get_secret_chat_state_object(secret_chat->state), secret_chat->is_outbound, secret_chat->ttl, get_secret_chat_state_object(secret_chat->state), secret_chat->is_outbound, secret_chat->ttl,
secret_chat->key_hash, secret_chat->layer); secret_chat->key_hash, secret_chat->layer);
} }
@ -14184,6 +14238,7 @@ td_api::object_ptr<td_api::botInfo> ContactsManager::get_bot_info_object(UserId
tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_info_object( tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_info_object(
const string &invite_link) const { const string &invite_link) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
auto it = invite_link_infos_.find(invite_link); auto it = invite_link_infos_.find(invite_link);
if (it == invite_link_infos_.end()) { if (it == invite_link_infos_.end()) {
return nullptr; return nullptr;
@ -14217,7 +14272,7 @@ tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_
LOG(ERROR) << "Have no information about " << chat_id; LOG(ERROR) << "Have no information about " << chat_id;
} }
chat_type = td_api::make_object<td_api::chatTypeBasicGroup>( chat_type = td_api::make_object<td_api::chatTypeBasicGroup>(
get_basic_group_id_object(chat_id, "get_chat_invite_link_info_object")); get_basic_group_id_object_internal(chat_id, "get_chat_invite_link_info_object"));
break; break;
} }
case DialogType::Channel: { case DialogType::Channel: {
@ -14236,7 +14291,7 @@ tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_
LOG(ERROR) << "Have no information about " << channel_id; LOG(ERROR) << "Have no information about " << channel_id;
} }
chat_type = td_api::make_object<td_api::chatTypeSupergroup>( chat_type = td_api::make_object<td_api::chatTypeSupergroup>(
get_supergroup_id_object(channel_id, "get_chat_invite_link_info_object"), !is_megagroup); get_supergroup_id_object_internal(channel_id, "get_chat_invite_link_info_object"), !is_megagroup);
break; break;
} }
default: default:
@ -14247,7 +14302,7 @@ tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_
invite_link_photo = as_fake_dialog_photo(invite_link_info->photo); invite_link_photo = as_fake_dialog_photo(invite_link_info->photo);
photo = &invite_link_photo; photo = &invite_link_photo;
participant_count = invite_link_info->participant_count; participant_count = invite_link_info->participant_count;
member_user_ids = get_user_ids_object(invite_link_info->participant_user_ids, "get_chat_invite_link_info_object"); member_user_ids = get_user_ids_object_internal(invite_link_info->participant_user_ids, "get_chat_invite_link_info_object");
is_public = invite_link_info->is_public; is_public = invite_link_info->is_public;
if (invite_link_info->is_chat) { if (invite_link_info->is_chat) {
@ -14274,6 +14329,7 @@ tl_object_ptr<td_api::chatInviteLinkInfo> ContactsManager::get_chat_invite_link_
} }
UserId ContactsManager::get_support_user(Promise<Unit> &&promise) { UserId ContactsManager::get_support_user(Promise<Unit> &&promise) {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
if (support_user_id_.is_valid()) { if (support_user_id_.is_valid()) {
promise.set_value(Unit()); promise.set_value(Unit());
return support_user_id_; return support_user_id_;
@ -14284,6 +14340,7 @@ UserId ContactsManager::get_support_user(Promise<Unit> &&promise) {
} }
void ContactsManager::after_get_difference() { void ContactsManager::after_get_difference() {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
if (td_->auth_manager_->is_bot()) { if (td_->auth_manager_->is_bot()) {
return; return;
} }
@ -14291,6 +14348,7 @@ void ContactsManager::after_get_difference() {
} }
void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const { void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const {
std::shared_lock<std::shared_timed_mutex> readerLock(memory_cleanup_mutex);
for (auto user_id : unknown_users_) { for (auto user_id : unknown_users_) {
if (!have_min_user(user_id)) { if (!have_min_user(user_id)) {
updates.push_back(get_update_unknown_user_object(user_id)); updates.push_back(get_update_unknown_user_object(user_id));
@ -14307,7 +14365,7 @@ void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update
} }
} }
for (auto secret_chat_id : unknown_secret_chats_) { for (auto secret_chat_id : unknown_secret_chats_) {
if (!have_secret_chat(secret_chat_id)) { if (!have_secret_chat_internal(secret_chat_id)) {
updates.push_back(get_update_unknown_secret_chat_object(secret_chat_id)); updates.push_back(get_update_unknown_secret_chat_object(secret_chat_id));
} }
} }
@ -14342,87 +14400,106 @@ void ContactsManager::get_current_state(vector<td_api::object_ptr<td_api::Update
} }
void ContactsManager::memory_cleanup() { void ContactsManager::memory_cleanup() {
users_.clear(); std::lock_guard<std::shared_timed_mutex> writerLock(memory_cleanup_mutex);
users_.rehash(0); users_.clear();
users_full_.clear(); users_.rehash(0);
users_full_.rehash(0); users_full_.clear();
bot_infos_.clear(); users_full_.rehash(0);
bot_infos_.rehash(0); bot_infos_.clear();
user_photos_.clear(); bot_infos_.rehash(0);
user_photos_.rehash(0); user_photos_.clear();
unknown_users_.clear(); user_photos_.rehash(0);
unknown_users_.rehash(0); unknown_users_.clear();
user_profile_photo_file_source_ids_.clear(); unknown_users_.rehash(0);
user_profile_photo_file_source_ids_.rehash(0); pending_user_photos_.clear();
my_photo_file_id_.clear(); pending_user_photos_.rehash(0);
my_photo_file_id_.rehash(0); user_profile_photo_file_source_ids_.clear();
chats_.clear(); user_profile_photo_file_source_ids_.rehash(0);
chats_.rehash(0); my_photo_file_id_.clear();
chats_full_.clear(); my_photo_file_id_.rehash(0);
chats_full_.rehash(0); chats_.clear();
unknown_chats_.clear(); chats_.rehash(0);
unknown_chats_.rehash(0); chats_full_.clear();
chat_full_file_source_ids_.clear(); chats_full_.rehash(0);
chat_full_file_source_ids_.rehash(0); unknown_chats_.clear();
min_channels_.clear(); unknown_chats_.rehash(0);
min_channels_.rehash(0); chat_full_file_source_ids_.clear();
channels_.clear(); chat_full_file_source_ids_.rehash(0);
channels_.rehash(0); min_channels_.clear();
channels_full_.clear(); min_channels_.rehash(0);
channels_full_.rehash(0); channels_.clear();
unknown_channels_.clear(); channels_.rehash(0);
unknown_channels_.rehash(0); channels_full_.clear();
channel_full_file_source_ids_.clear(); channels_full_.rehash(0);
channel_full_file_source_ids_.rehash(0); unknown_channels_.clear();
secret_chats_.clear(); unknown_channels_.rehash(0);
secret_chats_.rehash(0); channel_full_file_source_ids_.clear();
unknown_secret_chats_.clear(); channel_full_file_source_ids_.rehash(0);
unknown_secret_chats_.rehash(0); secret_chats_.clear();
secret_chats_with_user_.clear(); secret_chats_.rehash(0);
secret_chats_with_user_.rehash(0); unknown_secret_chats_.clear();
dialog_invite_links_.clear(); unknown_secret_chats_.rehash(0);
dialog_invite_links_.rehash(0); secret_chats_with_user_.clear();
invite_link_infos_.clear(); secret_chats_with_user_.rehash(0);
invite_link_infos_.rehash(0); dialog_invite_links_.clear();
dialog_access_by_invite_link_.clear(); dialog_invite_links_.rehash(0);
dialog_access_by_invite_link_.rehash(0); invite_link_infos_.clear();
loaded_from_database_users_.clear(); invite_link_infos_.rehash(0);
loaded_from_database_users_.rehash(0); dialog_access_by_invite_link_.clear();
unavailable_user_fulls_.clear(); dialog_access_by_invite_link_.rehash(0);
unavailable_user_fulls_.rehash(0); load_user_from_database_queries_.clear();
unavailable_bot_infos_.clear(); load_user_from_database_queries_.rehash(0);
unavailable_bot_infos_.rehash(0); loaded_from_database_users_.clear();
loaded_from_database_chats_.clear(); loaded_from_database_users_.rehash(0);
loaded_from_database_chats_.rehash(0); unavailable_user_fulls_.clear();
unavailable_chat_fulls_.clear(); unavailable_user_fulls_.rehash(0);
unavailable_chat_fulls_.rehash(0); unavailable_bot_infos_.clear();
loaded_from_database_channels_.clear(); unavailable_bot_infos_.rehash(0);
loaded_from_database_channels_.rehash(0); load_chat_from_database_queries_.clear();
loaded_from_database_secret_chats_.clear(); load_chat_from_database_queries_.rehash(0);
loaded_from_database_secret_chats_.rehash(0); loaded_from_database_chats_.clear();
dialog_administrators_.clear(); loaded_from_database_chats_.rehash(0);
dialog_administrators_.rehash(0); unavailable_chat_fulls_.clear();
uploaded_profile_photos_.clear(); unavailable_chat_fulls_.rehash(0);
uploaded_profile_photos_.rehash(0); load_channel_from_database_queries_.clear();
imported_contacts_.clear(); load_channel_from_database_queries_.rehash(0);
imported_contacts_.rehash(0); loaded_from_database_channels_.clear();
received_channel_participant_.clear(); loaded_from_database_channels_.rehash(0);
received_channel_participant_.rehash(0); unavailable_channel_fulls_.clear();
received_channel_participants_.clear(); unavailable_channel_fulls_.rehash(0);
received_channel_participants_.rehash(0); load_secret_chat_from_database_queries_.clear();
cached_channel_participants_.clear(); load_secret_chat_from_database_queries_.rehash(0);
cached_channel_participants_.rehash(0); loaded_from_database_secret_chats_.clear();
found_blocked_users_.clear(); loaded_from_database_secret_chats_.rehash(0);
found_blocked_users_.rehash(0); dialog_administrators_.clear();
all_users_nearby_.clear(); dialog_administrators_.rehash(0);
all_users_nearby_.rehash(0); uploaded_profile_photos_.clear();
linked_channel_ids_.clear(); uploaded_profile_photos_.rehash(0);
linked_channel_ids_.rehash(0); imported_contacts_.clear();
restricted_user_ids_.clear(); imported_contacts_.rehash(0);
restricted_user_ids_.rehash(0); received_channel_participant_.clear();
restricted_channel_ids_.clear(); received_channel_participant_.rehash(0);
restricted_channel_ids_.rehash(0); received_channel_participants_.clear();
restricted_channel_ids_.clear(); received_channel_participants_.rehash(0);
restricted_channel_ids_.rehash(0); cached_channel_participants_.clear();
cached_channel_participants_.rehash(0);
found_blocked_users_.clear();
found_blocked_users_.rehash(0);
load_contacts_queries_.clear();
load_imported_contacts_queries_.clear();
all_imported_contacts_.clear();
users_nearby_.clear();
channels_nearby_.clear();
all_users_nearby_.clear();
all_users_nearby_.rehash(0);
linked_channel_ids_.clear();
linked_channel_ids_.rehash(0);
restricted_user_ids_.clear();
restricted_user_ids_.rehash(0);
restricted_channel_ids_.clear();
restricted_channel_ids_.rehash(0);
next_all_imported_contacts_.clear();
imported_contact_user_ids_.clear();
unimported_contact_invites_.clear();
} }
} // namespace td } // namespace td

View File

@ -47,6 +47,7 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <utility> #include <utility>
#include <shared_mutex>
namespace td { namespace td {
@ -469,12 +470,14 @@ class ContactsManager : public Actor {
bool get_channel(ChannelId channel_id, int left_tries, Promise<Unit> &&promise); bool get_channel(ChannelId channel_id, int left_tries, Promise<Unit> &&promise);
void reload_channel(ChannelId chnanel_id, Promise<Unit> &&promise); void reload_channel(ChannelId chnanel_id, Promise<Unit> &&promise);
bool get_channel_full(ChannelId channel_id, bool force, Promise<Unit> &&promise); bool get_channel_full(ChannelId channel_id, bool force, Promise<Unit> &&promise);
bool get_channel_full_internal(ChannelId channel_id, bool force, Promise<Unit> &&promise);
FileSourceId get_channel_full_file_source_id(ChannelId channel_id); FileSourceId get_channel_full_file_source_id(ChannelId channel_id);
void reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source); void reload_channel_full(ChannelId channel_id, Promise<Unit> &&promise, const char *source);
bool is_channel_public(ChannelId channel_id) const; bool is_channel_public(ChannelId channel_id) const;
bool have_secret_chat(SecretChatId secret_chat_id) const; bool have_secret_chat(SecretChatId secret_chat_id) const;
bool have_secret_chat_internal(SecretChatId secret_chat_id) const;
bool have_secret_chat_force(SecretChatId secret_chat_id); bool have_secret_chat_force(SecretChatId secret_chat_id);
bool get_secret_chat(SecretChatId secret_chat_id, bool force, Promise<Unit> &&promise); bool get_secret_chat(SecretChatId secret_chat_id, bool force, Promise<Unit> &&promise);
bool get_secret_chat_full(SecretChatId secret_chat_id, Promise<Unit> &&promise); bool get_secret_chat_full(SecretChatId secret_chat_id, Promise<Unit> &&promise);
@ -489,6 +492,8 @@ class ContactsManager : public Actor {
std::pair<int32, vector<UserId>> search_among_users(const vector<UserId> &user_ids, const string &query, int32 limit); std::pair<int32, vector<UserId>> search_among_users(const vector<UserId> &user_ids, const string &query, int32 limit);
std::pair<int32, vector<UserId>> search_among_users_internal(const vector<UserId> &user_ids, const string &query, int32 limit);
DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise<Unit> &&promise); DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise<Unit> &&promise);
std::pair<int32, vector<DialogParticipant>> search_chat_participants(ChatId chat_id, const string &query, int32 limit, std::pair<int32, vector<DialogParticipant>> search_chat_participants(ChatId chat_id, const string &query, int32 limit,
@ -513,22 +518,32 @@ class ContactsManager : public Actor {
int32 get_user_id_object(UserId user_id, const char *source) const; int32 get_user_id_object(UserId user_id, const char *source) const;
int32 get_user_id_object_internal(UserId user_id, const char *source) const;
tl_object_ptr<td_api::user> get_user_object(UserId user_id) const; tl_object_ptr<td_api::user> get_user_object(UserId user_id) const;
vector<int32> get_user_ids_object(const vector<UserId> &user_ids, const char *source) const; vector<int32> get_user_ids_object(const vector<UserId> &user_ids, const char *source) const;
vector<int32> get_user_ids_object_internal(const vector<UserId> &user_ids, const char *source) const;
tl_object_ptr<td_api::users> get_users_object(int32 total_count, const vector<UserId> &user_ids) const; tl_object_ptr<td_api::users> get_users_object(int32 total_count, const vector<UserId> &user_ids) const;
tl_object_ptr<td_api::users> get_users_object_internal(int32 total_count, const vector<UserId> &user_ids) const;
tl_object_ptr<td_api::userFullInfo> get_user_full_info_object(UserId user_id) const; tl_object_ptr<td_api::userFullInfo> get_user_full_info_object(UserId user_id) const;
int32 get_basic_group_id_object(ChatId chat_id, const char *source) const; int32 get_basic_group_id_object(ChatId chat_id, const char *source) const;
int32 get_basic_group_id_object_internal(ChatId chat_id, const char *source) const;
tl_object_ptr<td_api::basicGroup> get_basic_group_object(ChatId chat_id); tl_object_ptr<td_api::basicGroup> get_basic_group_object(ChatId chat_id);
tl_object_ptr<td_api::basicGroupFullInfo> get_basic_group_full_info_object(ChatId chat_id) const; tl_object_ptr<td_api::basicGroupFullInfo> get_basic_group_full_info_object(ChatId chat_id) const;
int32 get_supergroup_id_object(ChannelId channel_id, const char *source) const; int32 get_supergroup_id_object(ChannelId channel_id, const char *source) const;
int32 get_supergroup_id_object_internal(ChannelId channel_id, const char *source) const;
tl_object_ptr<td_api::supergroup> get_supergroup_object(ChannelId channel_id) const; tl_object_ptr<td_api::supergroup> get_supergroup_object(ChannelId channel_id) const;
tl_object_ptr<td_api::supergroupFullInfo> get_supergroup_full_info_object(ChannelId channel_id) const; tl_object_ptr<td_api::supergroupFullInfo> get_supergroup_full_info_object(ChannelId channel_id) const;
@ -1086,7 +1101,9 @@ class ContactsManager : public Actor {
Channel *add_channel(ChannelId channel_id, const char *source); Channel *add_channel(ChannelId channel_id, const char *source);
const ChannelFull *get_channel_full(ChannelId channel_id) const; const ChannelFull *get_channel_full(ChannelId channel_id) const;
const ChannelFull *get_channel_full_internal(ChannelId channel_id) const;
ChannelFull *get_channel_full(ChannelId channel_id, const char *source); ChannelFull *get_channel_full(ChannelId channel_id, const char *source);
ChannelFull *get_channel_full_internal(ChannelId channel_id, const char *source);
ChannelFull *get_channel_full_force(ChannelId channel_id, const char *source); ChannelFull *get_channel_full_force(ChannelId channel_id, const char *source);
ChannelFull *add_channel_full(ChannelId channel_id); ChannelFull *add_channel_full(ChannelId channel_id);
@ -1587,6 +1604,8 @@ class ContactsManager : public Actor {
MultiTimeout user_nearby_timeout_{"UserNearbyTimeout"}; MultiTimeout user_nearby_timeout_{"UserNearbyTimeout"};
MultiTimeout slow_mode_delay_timeout_{"SlowModeDelayTimeout"}; MultiTimeout slow_mode_delay_timeout_{"SlowModeDelayTimeout"};
MultiTimeout invite_link_info_expire_timeout_{"InviteLinkInfoExpireTimeout"}; MultiTimeout invite_link_info_expire_timeout_{"InviteLinkInfoExpireTimeout"};
mutable std::shared_timed_mutex memory_cleanup_mutex;
}; };
} // namespace td } // namespace td