Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2022-08-06 22:08:15 +02:00
commit eadb920736
28 changed files with 339 additions and 310 deletions

View File

@ -88,6 +88,9 @@ function(td_set_up_compiler)
# _FILE_OFFSET_BITS is broken in Android NDK r15, r15b and r17 and doesn't work prior to Android 7.0 # _FILE_OFFSET_BITS is broken in Android NDK r15, r15b and r17 and doesn't work prior to Android 7.0
add_definitions(-D_FILE_OFFSET_BITS=64) add_definitions(-D_FILE_OFFSET_BITS=64)
# _GNU_SOURCE might not be defined by g++
add_definitions(-D_GNU_SOURCE)
if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl")
if (ILLUMOS) if (ILLUMOS)

View File

@ -3399,43 +3399,16 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent
} }
ContactsManager::~ContactsManager() { ContactsManager::~ContactsManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), users_); Scheduler::instance()->destroy_on_scheduler(
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), users_full_); G()->get_gc_scheduler_id(), users_, users_full_, user_photos_, unknown_users_, pending_user_photos_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_photos_); user_profile_photo_file_source_ids_, my_photo_file_id_, chats_, chats_full_, unknown_chats_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_users_); chat_full_file_source_ids_, min_channels_, channels_, channels_full_, unknown_channels_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), pending_user_photos_); invalidated_channels_full_, channel_full_file_source_ids_, secret_chats_, unknown_secret_chats_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_profile_photo_file_source_ids_); secret_chats_with_user_, invite_link_infos_, dialog_access_by_invite_link_, loaded_from_database_users_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), my_photo_file_id_); unavailable_user_fulls_, loaded_from_database_chats_, unavailable_chat_fulls_, loaded_from_database_channels_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chats_); unavailable_channel_fulls_, loaded_from_database_secret_chats_, dialog_administrators_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chats_full_); cached_channel_participants_, resolved_phone_numbers_, channel_participants_, all_imported_contacts_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_chats_); linked_channel_ids_, restricted_user_ids_, restricted_channel_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chat_full_file_source_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), min_channels_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channels_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channels_full_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_channels_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), invalidated_channels_full_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channel_full_file_source_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), secret_chats_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_secret_chats_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), secret_chats_with_user_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), invite_link_infos_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_access_by_invite_link_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_users_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unavailable_user_fulls_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_chats_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unavailable_chat_fulls_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_channels_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unavailable_channel_fulls_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_secret_chats_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_administrators_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), cached_channel_participants_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), resolved_phone_numbers_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channel_participants_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), all_imported_contacts_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), linked_channel_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), restricted_user_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), restricted_channel_ids_);
} }
void ContactsManager::tear_down() { void ContactsManager::tear_down() {
@ -8795,23 +8768,24 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr,
class ContactsManager::UserLogEvent { class ContactsManager::UserLogEvent {
public: public:
UserId user_id; UserId user_id;
User u; const User *u_in = nullptr;
unique_ptr<User> u_out;
UserLogEvent() = default; UserLogEvent() = default;
UserLogEvent(UserId user_id, const User &u) : user_id(user_id), u(u) { UserLogEvent(UserId user_id, const User *u) : user_id(user_id), u_in(u) {
} }
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
td::store(user_id, storer); td::store(user_id, storer);
td::store(u, storer); td::store(*u_in, storer);
} }
template <class ParserT> template <class ParserT>
void parse(ParserT &parser) { void parse(ParserT &parser) {
td::parse(user_id, parser); td::parse(user_id, parser);
td::parse(u, parser); td::parse(u_out, parser);
} }
}; };
@ -8830,7 +8804,7 @@ void ContactsManager::save_user(User *u, UserId user_id, bool from_binlog) {
make_tl_object<td_api::updateAccessHash>(get_user_access_hash_object(user_id, u))); make_tl_object<td_api::updateAccessHash>(get_user_access_hash_object(user_id, u)));
} }
if (!from_binlog) { if (!from_binlog) {
auto log_event = UserLogEvent(user_id, *u); auto log_event = UserLogEvent(user_id, u);
auto storer = get_log_event_storer(log_event); auto storer = get_log_event_storer(log_event);
if (u->log_event_id == 0) { if (u->log_event_id == 0) {
u->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Users, storer); u->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Users, storer);
@ -8860,8 +8834,8 @@ void ContactsManager::on_binlog_user_event(BinlogEvent &&event) {
} }
LOG(INFO) << "Add " << user_id << " from binlog"; LOG(INFO) << "Add " << user_id << " from binlog";
User *u = add_user(user_id, "on_binlog_user_event"); User *u = users_.emplace(user_id, std::move(log_event.u_out)).first->second.get();
*u = std::move(log_event.u); // users come from binlog before all other events, so just add them CHECK(u != nullptr);
u->log_event_id = event.id_; u->log_event_id = event.id_;
@ -9109,23 +9083,24 @@ ContactsManager::User *ContactsManager::get_user_force_impl(UserId user_id) {
class ContactsManager::ChatLogEvent { class ContactsManager::ChatLogEvent {
public: public:
ChatId chat_id; ChatId chat_id;
Chat c; const Chat *c_in = nullptr;
unique_ptr<Chat> c_out;
ChatLogEvent() = default; ChatLogEvent() = default;
ChatLogEvent(ChatId chat_id, const Chat &c) : chat_id(chat_id), c(c) { ChatLogEvent(ChatId chat_id, const Chat *c) : chat_id(chat_id), c_in(c) {
} }
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
td::store(chat_id, storer); td::store(chat_id, storer);
td::store(c, storer); td::store(*c_in, storer);
} }
template <class ParserT> template <class ParserT>
void parse(ParserT &parser) { void parse(ParserT &parser) {
td::parse(chat_id, parser); td::parse(chat_id, parser);
td::parse(c, parser); td::parse(c_out, parser);
} }
}; };
@ -9136,7 +9111,7 @@ void ContactsManager::save_chat(Chat *c, ChatId chat_id, bool from_binlog) {
CHECK(c != nullptr); CHECK(c != nullptr);
if (!c->is_saved) { if (!c->is_saved) {
if (!from_binlog) { if (!from_binlog) {
auto log_event = ChatLogEvent(chat_id, *c); auto log_event = ChatLogEvent(chat_id, c);
auto storer = get_log_event_storer(log_event); auto storer = get_log_event_storer(log_event);
if (c->log_event_id == 0) { if (c->log_event_id == 0) {
c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Chats, storer); c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Chats, storer);
@ -9167,8 +9142,8 @@ void ContactsManager::on_binlog_chat_event(BinlogEvent &&event) {
} }
LOG(INFO) << "Add " << chat_id << " from binlog"; LOG(INFO) << "Add " << chat_id << " from binlog";
Chat *c = add_chat(chat_id); Chat *c = chats_.emplace(chat_id, std::move(log_event.c_out)).first->second.get();
*c = std::move(log_event.c); // chats come from binlog before all other events, so just add them CHECK(c != nullptr);
c->log_event_id = event.id_; c->log_event_id = event.id_;
@ -9346,23 +9321,24 @@ ContactsManager::Chat *ContactsManager::get_chat_force(ChatId chat_id) {
class ContactsManager::ChannelLogEvent { class ContactsManager::ChannelLogEvent {
public: public:
ChannelId channel_id; ChannelId channel_id;
Channel c; const Channel *c_in = nullptr;
unique_ptr<Channel> c_out;
ChannelLogEvent() = default; ChannelLogEvent() = default;
ChannelLogEvent(ChannelId channel_id, const Channel &c) : channel_id(channel_id), c(c) { ChannelLogEvent(ChannelId channel_id, const Channel *c) : channel_id(channel_id), c_in(c) {
} }
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
td::store(channel_id, storer); td::store(channel_id, storer);
td::store(c, storer); td::store(*c_in, storer);
} }
template <class ParserT> template <class ParserT>
void parse(ParserT &parser) { void parse(ParserT &parser) {
td::parse(channel_id, parser); td::parse(channel_id, parser);
td::parse(c, parser); td::parse(c_out, parser);
} }
}; };
@ -9381,7 +9357,7 @@ void ContactsManager::save_channel(Channel *c, ChannelId channel_id, bool from_b
make_tl_object<td_api::updateAccessHash>(get_channel_access_hash_object(channel_id, c))); make_tl_object<td_api::updateAccessHash>(get_channel_access_hash_object(channel_id, c)));
} }
if (!from_binlog) { if (!from_binlog) {
auto log_event = ChannelLogEvent(channel_id, *c); auto log_event = ChannelLogEvent(channel_id, c);
auto storer = get_log_event_storer(log_event); auto storer = get_log_event_storer(log_event);
if (c->log_event_id == 0) { if (c->log_event_id == 0) {
c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Channels, storer); c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::Channels, storer);
@ -9412,8 +9388,8 @@ void ContactsManager::on_binlog_channel_event(BinlogEvent &&event) {
} }
LOG(INFO) << "Add " << channel_id << " from binlog"; LOG(INFO) << "Add " << channel_id << " from binlog";
Channel *c = add_channel(channel_id, "on_binlog_channel_event"); Channel *c = channels_.emplace(channel_id, std::move(log_event.c_out)).first->second.get();
*c = std::move(log_event.c); // channels come from binlog before all other events, so just add them CHECK(c != nullptr);
c->log_event_id = event.id_; c->log_event_id = event.id_;
@ -9607,23 +9583,24 @@ ContactsManager::Channel *ContactsManager::get_channel_force(ChannelId channel_i
class ContactsManager::SecretChatLogEvent { class ContactsManager::SecretChatLogEvent {
public: public:
SecretChatId secret_chat_id; SecretChatId secret_chat_id;
SecretChat c; const SecretChat *c_in = nullptr;
unique_ptr<SecretChat> c_out;
SecretChatLogEvent() = default; SecretChatLogEvent() = default;
SecretChatLogEvent(SecretChatId secret_chat_id, const SecretChat &c) : secret_chat_id(secret_chat_id), c(c) { SecretChatLogEvent(SecretChatId secret_chat_id, const SecretChat *c) : secret_chat_id(secret_chat_id), c_in(c) {
} }
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
td::store(secret_chat_id, storer); td::store(secret_chat_id, storer);
td::store(c, storer); td::store(*c_in, storer);
} }
template <class ParserT> template <class ParserT>
void parse(ParserT &parser) { void parse(ParserT &parser) {
td::parse(secret_chat_id, parser); td::parse(secret_chat_id, parser);
td::parse(c, parser); td::parse(c_out, parser);
} }
}; };
@ -9634,7 +9611,7 @@ void ContactsManager::save_secret_chat(SecretChat *c, SecretChatId secret_chat_i
CHECK(c != nullptr); CHECK(c != nullptr);
if (!c->is_saved) { if (!c->is_saved) {
if (!from_binlog) { if (!from_binlog) {
auto log_event = SecretChatLogEvent(secret_chat_id, *c); auto log_event = SecretChatLogEvent(secret_chat_id, c);
auto storer = get_log_event_storer(log_event); auto storer = get_log_event_storer(log_event);
if (c->log_event_id == 0) { if (c->log_event_id == 0) {
c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SecretChatInfos, storer); c->log_event_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SecretChatInfos, storer);
@ -9665,8 +9642,8 @@ void ContactsManager::on_binlog_secret_chat_event(BinlogEvent &&event) {
} }
LOG(INFO) << "Add " << secret_chat_id << " from binlog"; LOG(INFO) << "Add " << secret_chat_id << " from binlog";
SecretChat *c = add_secret_chat(secret_chat_id); SecretChat *c = secret_chats_.emplace(secret_chat_id, std::move(log_event.c_out)).first->second.get();
*c = std::move(log_event.c); // secret chats come from binlog before all other events, so just add them CHECK(c != nullptr);
c->log_event_id = event.id_; c->log_event_id = event.id_;

View File

@ -6,7 +6,6 @@
// //
#include "td/telegram/DownloadManager.h" #include "td/telegram/DownloadManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileId.hpp" #include "td/telegram/files/FileId.hpp"
#include "td/telegram/files/FileSourceId.hpp" #include "td/telegram/files/FileSourceId.hpp"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
@ -83,64 +82,43 @@ class DownloadManagerImpl final : public DownloadManager {
load_database_files(); load_database_files();
} }
Status toggle_is_paused(FileId file_id, bool is_paused) final { void toggle_is_paused(FileId file_id, bool is_paused, Promise<Unit> promise) final {
TRY_STATUS(check_is_active()); TRY_STATUS_PROMISE(promise, check_is_active());
TRY_RESULT(file_info_ptr, get_file_info(file_id)); TRY_RESULT_PROMISE(promise, file_info_ptr, get_file_info(file_id));
toggle_is_paused(*file_info_ptr, is_paused); toggle_is_paused(*file_info_ptr, is_paused);
return Status::OK(); promise.set_value(Unit());
} }
Status toggle_all_is_paused(bool is_paused) final { void toggle_all_is_paused(bool is_paused, Promise<Unit> promise) final {
TRY_STATUS(check_is_active()); TRY_STATUS_PROMISE(promise, check_is_active());
vector<FileId> to_toggle;
for (auto &it : files_) { for (auto &it : files_) {
toggle_is_paused(*it.second, is_paused); FileInfo &file_info = *it.second;
if (!is_completed(file_info) && is_paused != file_info.is_paused) {
to_toggle.push_back(file_info.file_id);
}
}
for (auto file_id : to_toggle) {
auto r_file_info_ptr = get_file_info(file_id);
if (r_file_info_ptr.is_ok()) {
toggle_is_paused(*r_file_info_ptr.ok(), is_paused);
}
} }
return Status::OK(); promise.set_value(Unit());
} }
Status remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) final { void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache, Promise<Unit> promise) final {
LOG(INFO) << "Remove from downloads file " << file_id << " from " << file_source_id; promise.set_result(remove_file_impl(file_id, file_source_id, delete_from_cache));
TRY_STATUS(check_is_active());
TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id));
auto &file_info = *file_info_ptr;
auto download_id = file_info.download_id;
if (!is_completed(file_info) && !file_info.is_paused) {
callback_->pause_file(file_info.internal_file_id);
}
unregister_file_info(file_info);
if (delete_from_cache) {
callback_->delete_file(file_info.internal_file_id);
}
by_internal_file_id_.erase(file_info.internal_file_id);
by_file_id_.erase(file_info.file_id);
hints_.remove(download_id);
completed_download_ids_.erase(download_id);
remove_from_database(file_info);
files_.erase(download_id);
if (is_search_inited_) {
callback_->update_file_removed(file_id, file_counters_);
}
update_counters();
on_file_viewed(download_id);
return Status::OK();
} }
Status remove_file_if_finished(FileId file_id) { void remove_file_if_finished(FileId file_id) final {
TRY_STATUS(check_is_active()); remove_file_if_finished_impl(file_id).ignore();
TRY_RESULT(file_info_ptr, get_file_info(file_id, {}));
if (!is_completed(*file_info_ptr)) {
return Status::Error("File is active");
}
return remove_file(file_id, {}, false);
} }
Status remove_all_files(bool only_active, bool only_completed, bool delete_from_cache) final { void remove_all_files(bool only_active, bool only_completed, bool delete_from_cache, Promise<Unit> promise) final {
TRY_STATUS(check_is_active()); TRY_STATUS_PROMISE(promise, check_is_active());
vector<FileId> to_remove; vector<FileId> to_remove;
for (auto &it : files_) { for (auto &it : files_) {
FileInfo &file_info = *it.second; FileInfo &file_info = *it.second;
@ -153,15 +131,16 @@ class DownloadManagerImpl final : public DownloadManager {
to_remove.push_back(file_info.file_id); to_remove.push_back(file_info.file_id);
} }
for (auto file_id : to_remove) { for (auto file_id : to_remove) {
remove_file(file_id, {}, delete_from_cache); remove_file_impl(file_id, {}, delete_from_cache);
} }
return Status::OK(); promise.set_value(Unit());
} }
Status add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority) final { void add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority,
TRY_STATUS(check_is_active()); Promise<td_api::object_ptr<td_api::file>> promise) final {
TRY_STATUS_PROMISE(promise, check_is_active());
remove_file(file_id, {}, false); remove_file_impl(file_id, {}, false);
auto download_id = next_download_id(); auto download_id = next_download_id();
@ -176,19 +155,23 @@ class DownloadManagerImpl final : public DownloadManager {
add_file_info(std::move(file_info), search_text); add_file_info(std::move(file_info), search_text);
return Status::OK(); promise.set_value(callback_->get_file_object(file_id));
} }
Status change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) final { void change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) final {
if (!is_search_inited_) { if (!is_search_inited_) {
return Status::OK(); return;
} }
TRY_STATUS(check_is_active()); if (check_is_active().is_error()) {
TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id)); return;
auto &file_info = *file_info_ptr; }
auto r_file_info_ptr = get_file_info(file_id, file_source_id);
if (r_file_info_ptr.is_error()) {
return;
}
auto &file_info = *r_file_info_ptr.ok();
hints_.add(file_info.download_id, search_text.empty() ? string(" ") : search_text); hints_.add(file_info.download_id, search_text.empty() ? string(" ") : search_text);
return Status::OK();
} }
void hints_synchronized(Result<Unit>) { void hints_synchronized(Result<Unit>) {
@ -328,7 +311,7 @@ class DownloadManagerImpl final : public DownloadManager {
return; return;
} }
auto &file_info = *r_file_info_ptr.ok(); auto &file_info = *r_file_info_ptr.ok();
remove_file(file_info.file_id, {}, false); remove_file_impl(file_info.file_id, {}, false);
} }
void update_file_viewed(FileId file_id, FileSourceId file_source_id) final { void update_file_viewed(FileId file_id, FileSourceId file_source_id) final {
@ -376,6 +359,7 @@ class DownloadManagerImpl final : public DownloadManager {
Counters sent_counters_; Counters sent_counters_;
FileCounters file_counters_; FileCounters file_counters_;
bool is_inited_{false}; bool is_inited_{false};
bool is_database_being_loaded_{false};
bool is_database_loaded_{false}; bool is_database_loaded_{false};
bool is_search_inited_{false}; bool is_search_inited_{false};
int64 max_download_id_{0}; int64 max_download_id_{0};
@ -488,6 +472,8 @@ class DownloadManagerImpl final : public DownloadManager {
return; return;
} }
CHECK(is_inited_); CHECK(is_inited_);
CHECK(!is_database_being_loaded_);
is_database_being_loaded_ = true;
LOG(INFO) << "Start Download Manager database loading"; LOG(INFO) << "Start Download Manager database loading";
@ -503,6 +489,7 @@ class DownloadManagerImpl final : public DownloadManager {
} }
is_database_loaded_ = true; is_database_loaded_ = true;
is_database_being_loaded_ = false;
update_counters(); update_counters();
check_completed_downloads_size(); check_completed_downloads_size();
@ -512,13 +499,13 @@ class DownloadManagerImpl final : public DownloadManager {
void prepare_hints() { void prepare_hints() {
for (auto &it : files_) { for (auto &it : files_) {
const auto &file_info = *it.second; const auto &file_info = *it.second;
send_closure(G()->file_reference_manager(), &FileReferenceManager::get_file_search_text, file_info.file_source_id, auto promise =
callback_->get_file_view(file_info.file_id).get_unique_file_id(), PromiseCreator::lambda([actor_id = actor_id(this), promise = load_search_text_multipromise_.get_promise(),
[actor_id = actor_id(this), promise = load_search_text_multipromise_.get_promise(), download_id = it.first](Result<string> r_search_text) mutable {
download_id = it.first](Result<string> r_search_text) mutable { send_closure(actor_id, &DownloadManagerImpl::add_download_to_hints, download_id, std::move(r_search_text),
send_closure(actor_id, &DownloadManagerImpl::add_download_to_hints, download_id, std::move(promise));
std::move(r_search_text), std::move(promise)); });
}); callback_->get_file_search_text(file_info.file_id, file_info.file_source_id, std::move(promise));
} }
} }
@ -530,7 +517,7 @@ class DownloadManagerImpl final : public DownloadManager {
if (r_search_text.is_error()) { if (r_search_text.is_error()) {
if (!G()->close_flag()) { if (!G()->close_flag()) {
remove_file(it->second->file_id, {}, false); remove_file_impl(it->second->file_id, {}, false);
} }
} else { } else {
auto search_text = r_search_text.move_as_ok(); auto search_text = r_search_text.move_as_ok();
@ -567,11 +554,8 @@ class DownloadManagerImpl final : public DownloadManager {
<< file_info->size << '/' << file_info->expected_size << file_info->size << '/' << file_info->expected_size
<< " with downloaded_size = " << file_info->downloaded_size << " with downloaded_size = " << file_info->downloaded_size
<< " and is_paused = " << file_info->is_paused; << " and is_paused = " << file_info->is_paused;
auto res = files_.emplace(download_id, std::move(file_info)); auto it = files_.emplace(download_id, std::move(file_info)).first;
auto it = res.first;
bool was_completed = is_completed(*it->second); bool was_completed = is_completed(*it->second);
LOG_CHECK(!it->second->is_registered)
<< res.second << ' ' << download_id << ' ' << max_download_id_ << ' ' << it->second->need_save_to_database;
register_file_info(*it->second); // must be called before start_file, which can call update_file_download_state register_file_info(*it->second); // must be called before start_file, which can call update_file_download_state
if (is_completed(*it->second)) { if (is_completed(*it->second)) {
bool is_inserted = completed_download_ids_.insert(it->second->download_id).second; bool is_inserted = completed_download_ids_.insert(it->second->download_id).second;
@ -588,6 +572,45 @@ class DownloadManagerImpl final : public DownloadManager {
} }
} }
Status remove_file_impl(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) {
LOG(INFO) << "Remove from downloads file " << file_id << " from " << file_source_id;
TRY_STATUS(check_is_active());
TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id));
auto &file_info = *file_info_ptr;
auto download_id = file_info.download_id;
if (!is_completed(file_info) && !file_info.is_paused) {
callback_->pause_file(file_info.internal_file_id);
}
unregister_file_info(file_info);
if (delete_from_cache) {
callback_->delete_file(file_info.internal_file_id);
}
by_internal_file_id_.erase(file_info.internal_file_id);
by_file_id_.erase(file_info.file_id);
hints_.remove(download_id);
completed_download_ids_.erase(download_id);
remove_from_database(file_info);
files_.erase(download_id);
if (is_search_inited_) {
callback_->update_file_removed(file_id, file_counters_);
}
update_counters();
on_file_viewed(download_id);
return Status::OK();
}
Status remove_file_if_finished_impl(FileId file_id) {
TRY_STATUS(check_is_active());
TRY_RESULT(file_info_ptr, get_file_info(file_id, {}));
if (!is_completed(*file_info_ptr)) {
return Status::Error("File is active");
}
return remove_file_impl(file_id, {}, false);
}
void timeout_expired() final { void timeout_expired() final {
clear_counters(); clear_counters();
} }
@ -756,7 +779,7 @@ class DownloadManagerImpl final : public DownloadManager {
while (completed_download_ids_.size() > MAX_COMPLETED_DOWNLOADS) { while (completed_download_ids_.size() > MAX_COMPLETED_DOWNLOADS) {
auto download_id = *completed_download_ids_.begin(); auto download_id = *completed_download_ids_.begin();
auto file_info = get_file_info(download_id).move_as_ok(); auto file_info = get_file_info(download_id).move_as_ok();
remove_file(file_info->file_id, FileSourceId(), false); remove_file_impl(file_info->file_id, FileSourceId(), false);
} }
} }

View File

@ -73,8 +73,10 @@ class DownloadManager : public Actor {
virtual void delete_file(FileId file_id) = 0; virtual void delete_file(FileId file_id) = 0;
virtual FileId dup_file_id(FileId file_id) = 0; virtual FileId dup_file_id(FileId file_id) = 0;
virtual FileView get_file_view(FileId file_id) = 0; virtual void get_file_search_text(FileId file_id, FileSourceId file_source_id, Promise<string> &&promise) = 0;
virtual FileView get_sync_file_view(FileId file_id) = 0; virtual FileView get_sync_file_view(FileId file_id) = 0;
virtual td_api::object_ptr<td_api::file> get_file_object(FileId file_id) = 0;
virtual td_api::object_ptr<td_api::fileDownload> get_file_download_object(FileId file_id, virtual td_api::object_ptr<td_api::fileDownload> get_file_download_object(FileId file_id,
FileSourceId file_source_id, FileSourceId file_source_id,
int32 add_date, int32 complete_date, int32 add_date, int32 complete_date,
@ -86,20 +88,23 @@ class DownloadManager : public Actor {
// //
// public interface for user // public interface for user
// //
virtual void after_get_difference() = 0; virtual void add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority,
virtual Status add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority) = 0; Promise<td_api::object_ptr<td_api::file>> promise) = 0;
virtual Status change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) = 0; virtual void toggle_is_paused(FileId file_id, bool is_paused, Promise<Unit> promise) = 0;
virtual Status toggle_is_paused(FileId file_id, bool is_paused) = 0; virtual void toggle_all_is_paused(bool is_paused, Promise<Unit> promise) = 0;
virtual Status toggle_all_is_paused(bool is_paused) = 0;
virtual void search(string query, bool only_active, bool only_completed, string offset, int32 limit, virtual void search(string query, bool only_active, bool only_completed, string offset, int32 limit,
Promise<td_api::object_ptr<td_api::foundFileDownloads>> promise) = 0; Promise<td_api::object_ptr<td_api::foundFileDownloads>> promise) = 0;
virtual Status remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) = 0; virtual void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache,
virtual Status remove_file_if_finished(FileId file_id) = 0; Promise<Unit> promise) = 0;
virtual Status remove_all_files(bool only_active, bool only_completed, bool delete_from_cache) = 0; virtual void remove_all_files(bool only_active, bool only_completed, bool delete_from_cache,
Promise<Unit> promise) = 0;
// //
// private interface to handle all kinds of updates // private interface to handle all kinds of updates
// //
virtual void after_get_difference() = 0;
virtual void change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) = 0;
virtual void remove_file_if_finished(FileId file_id) = 0;
virtual void update_file_download_state(FileId internal_file_id, int64 downloaded_size, int64 size, virtual void update_file_download_state(FileId internal_file_id, int64 downloaded_size, int64 size,
int64 expected_size, bool is_paused) = 0; int64 expected_size, bool is_paused) = 0;
virtual void update_file_deleted(FileId internal_file_id) = 0; virtual void update_file_deleted(FileId internal_file_id) = 0;

View File

@ -64,6 +64,12 @@ FileId DownloadManagerCallback::dup_file_id(FileId file_id) {
return td_->file_manager_->dup_file_id(file_id); return td_->file_manager_->dup_file_id(file_id);
} }
void DownloadManagerCallback::get_file_search_text(FileId file_id, FileSourceId file_source_id,
Promise<string> &&promise) {
send_closure(td_->file_reference_manager_actor_, &FileReferenceManager::get_file_search_text, file_source_id,
get_file_view(file_id).get_unique_file_id(), std::move(promise));
}
FileView DownloadManagerCallback::get_file_view(FileId file_id) { FileView DownloadManagerCallback::get_file_view(FileId file_id) {
return td_->file_manager_->get_file_view(file_id); return td_->file_manager_->get_file_view(file_id);
} }
@ -73,6 +79,10 @@ FileView DownloadManagerCallback::get_sync_file_view(FileId file_id) {
return get_file_view(file_id); return get_file_view(file_id);
} }
td_api::object_ptr<td_api::file> DownloadManagerCallback::get_file_object(FileId file_id) {
return td_->file_manager_->get_file_object(file_id);
}
td_api::object_ptr<td_api::fileDownload> DownloadManagerCallback::get_file_download_object( td_api::object_ptr<td_api::fileDownload> DownloadManagerCallback::get_file_download_object(
FileId file_id, FileSourceId file_source_id, int32 add_date, int32 complete_date, bool is_paused) { FileId file_id, FileSourceId file_source_id, int32 add_date, int32 complete_date, bool is_paused) {
return td_api::make_object<td_api::fileDownload>(td_->file_manager_->get_file_view(file_id).get_main_file_id().get(), return td_api::make_object<td_api::fileDownload>(td_->file_manager_->get_file_view(file_id).get_main_file_id().get(),

View File

@ -45,18 +45,22 @@ class DownloadManagerCallback final : public DownloadManager::Callback {
FileId dup_file_id(FileId file_id) final; FileId dup_file_id(FileId file_id) final;
FileView get_file_view(FileId file_id) final; void get_file_search_text(FileId file_id, FileSourceId file_source_id, Promise<string> &&promise) final;
FileView get_sync_file_view(FileId file_id) final; FileView get_sync_file_view(FileId file_id) final;
td_api::object_ptr<td_api::file> get_file_object(FileId file_id) final;
td_api::object_ptr<td_api::fileDownload> get_file_download_object(FileId file_id, FileSourceId file_source_id, td_api::object_ptr<td_api::fileDownload> get_file_download_object(FileId file_id, FileSourceId file_source_id,
int32 add_date, int32 complete_date, int32 add_date, int32 complete_date,
bool is_paused); bool is_paused) final;
private: private:
Td *td_; Td *td_;
ActorShared<> parent_; ActorShared<> parent_;
FileView get_file_view(FileId file_id);
static std::shared_ptr<FileManager::DownloadCallback> make_download_file_callback( static std::shared_ptr<FileManager::DownloadCallback> make_download_file_callback(
Td *td, ActorShared<DownloadManager> download_manager); Td *td, ActorShared<DownloadManager> download_manager);
}; };

View File

@ -1057,7 +1057,7 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
nullptr, std::move(user_link), url_query.get_arg("attach").str(), url_query.get_arg("startattach")); nullptr, std::move(user_link), url_query.get_arg("attach").str(), url_query.get_arg("startattach"));
} }
// resolve?phone=12345 // resolve?phone=12345
return user_link; return std::move(user_link);
} }
} else if (path.size() == 1 && path[0] == "login") { } else if (path.size() == 1 && path[0] == "login") {
// login?code=123456 // login?code=123456
@ -1239,7 +1239,7 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_t_me_link_query(Slice q
nullptr, std::move(user_link), url_query.get_arg("attach").str(), url_query.get_arg("startattach")); nullptr, std::move(user_link), url_query.get_arg("attach").str(), url_query.get_arg("startattach"));
} }
// /+<phone_number> // /+<phone_number>
return user_link; return std::move(user_link);
} else { } else {
// /+<link> // /+<link>
return td::make_unique<InternalLinkDialogInvite>(PSTRING() << "tg:join?invite=" return td::make_unique<InternalLinkDialogInvite>(PSTRING() << "tg:join?invite="

View File

@ -51,6 +51,7 @@
#include "td/telegram/NotificationSettingsManager.h" #include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/NotificationSound.h" #include "td/telegram/NotificationSound.h"
#include "td/telegram/NotificationType.h" #include "td/telegram/NotificationType.h"
#include "td/telegram/PollId.h"
#include "td/telegram/PublicDialogType.h" #include "td/telegram/PublicDialogType.h"
#include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.h"
#include "td/telegram/ReplyMarkup.hpp" #include "td/telegram/ReplyMarkup.hpp"
@ -5810,34 +5811,16 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent)
} }
MessagesManager::~MessagesManager() { MessagesManager::~MessagesManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), ttl_nodes_); Scheduler::instance()->destroy_on_scheduler(
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), ttl_heap_); G()->get_gc_scheduler_id(), ttl_nodes_, ttl_heap_, being_sent_messages_, update_message_ids_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), being_sent_messages_); update_scheduled_message_ids_, message_id_to_dialog_id_, last_clear_history_message_id_to_dialog_id_, dialogs_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), update_message_ids_); postponed_chat_read_inbox_updates_, found_public_dialogs_, found_on_server_dialogs_, found_common_dialogs_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), update_scheduled_message_ids_); message_embedding_codes_[0], message_embedding_codes_[1], replied_by_media_timestamp_messages_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_id_to_dialog_id_); notification_group_id_to_dialog_id_, active_get_channel_differencies_, get_channel_difference_to_log_event_id_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), last_clear_history_message_id_to_dialog_id_); channel_get_difference_retry_timeouts_, is_channel_difference_finished_, resolved_usernames_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialogs_); inaccessible_resolved_usernames_, dialog_bot_command_message_ids_, full_message_id_to_file_source_id_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), postponed_chat_read_inbox_updates_); last_outgoing_forwarded_message_date_, dialog_viewed_messages_, dialog_online_member_counts_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_public_dialogs_); previous_repaired_read_inbox_max_message_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_on_server_dialogs_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_common_dialogs_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_embedding_codes_[0]);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_embedding_codes_[1]);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), replied_by_media_timestamp_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), notification_group_id_to_dialog_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), active_get_channel_differencies_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), get_channel_difference_to_log_event_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), channel_get_difference_retry_timeouts_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), is_channel_difference_finished_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), resolved_usernames_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), inaccessible_resolved_usernames_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_bot_command_message_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), full_message_id_to_file_source_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), last_outgoing_forwarded_message_date_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_viewed_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialog_online_member_counts_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), previous_repaired_read_inbox_max_message_id_);
} }
void MessagesManager::on_channel_get_difference_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) { void MessagesManager::on_channel_get_difference_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) {
@ -20806,7 +20789,8 @@ Status MessagesManager::view_messages(DialogId dialog_id, MessageId top_thread_m
for (auto file_id : get_message_file_ids(m)) { for (auto file_id : get_message_file_ids(m)) {
auto file_view = td_->file_manager_->get_file_view(file_id); auto file_view = td_->file_manager_->get_file_view(file_id);
CHECK(!file_view.empty()); CHECK(!file_view.empty());
td_->download_manager_->update_file_viewed(file_view.get_main_file_id(), file_source_id); send_closure(td_->download_manager_actor_, &DownloadManager::update_file_viewed, file_view.get_main_file_id(),
file_source_id);
} }
} }
@ -22975,7 +22959,7 @@ void MessagesManager::remove_message_file_sources(DialogId dialog_id, const Mess
for (auto file_id : file_ids) { for (auto file_id : file_ids) {
auto file_view = td_->file_manager_->get_file_view(file_id); auto file_view = td_->file_manager_->get_file_view(file_id);
send_closure(td_->download_manager_actor_, &DownloadManager::remove_file, file_view.get_main_file_id(), send_closure(td_->download_manager_actor_, &DownloadManager::remove_file, file_view.get_main_file_id(),
file_source_id, false); file_source_id, false, Promise<Unit>());
td_->file_manager_->remove_file_source(file_id, file_source_id); td_->file_manager_->remove_file_source(file_id, file_source_id);
} }
} }
@ -23002,7 +22986,7 @@ void MessagesManager::change_message_files(DialogId dialog_id, const Message *m,
if (file_source_id.is_valid()) { if (file_source_id.is_valid()) {
auto file_view = td_->file_manager_->get_file_view(file_id); auto file_view = td_->file_manager_->get_file_view(file_id);
send_closure(td_->download_manager_actor_, &DownloadManager::remove_file, file_view.get_main_file_id(), send_closure(td_->download_manager_actor_, &DownloadManager::remove_file, file_view.get_main_file_id(),
file_source_id, false); file_source_id, false, Promise<Unit>());
} }
} }
} }
@ -28032,8 +28016,8 @@ class MessagesManager::ForwardMessagesLogEvent {
DialogId from_dialog_id; DialogId from_dialog_id;
vector<MessageId> message_ids; vector<MessageId> message_ids;
vector<Message *> messages_in; vector<Message *> messages_in;
bool drop_author = false; bool drop_author;
bool drop_media_captions = false; bool drop_media_captions;
vector<unique_ptr<Message>> messages_out; vector<unique_ptr<Message>> messages_out;
template <class StorerT> template <class StorerT>
@ -28055,6 +28039,9 @@ class MessagesManager::ForwardMessagesLogEvent {
PARSE_FLAG(drop_author); PARSE_FLAG(drop_author);
PARSE_FLAG(drop_media_captions); PARSE_FLAG(drop_media_captions);
END_PARSE_FLAGS(); END_PARSE_FLAGS();
} else {
drop_author = false;
drop_media_captions = false;
} }
td::parse(to_dialog_id, parser); td::parse(to_dialog_id, parser);
td::parse(from_dialog_id, parser); td::parse(from_dialog_id, parser);
@ -28190,6 +28177,9 @@ unique_ptr<MessagesManager::MessageForwardInfo> MessagesManager::create_message_
void MessagesManager::fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message, void MessagesManager::fix_forwarded_message(Message *m, DialogId to_dialog_id, const Message *forwarded_message,
int64 media_album_id, bool drop_author) const { int64 media_album_id, bool drop_author) const {
if (m->content->get_type() == MessageContentType::Audio) {
drop_author = true;
}
bool is_game = m->content->get_type() == MessageContentType::Game; bool is_game = m->content->get_type() == MessageContentType::Game;
if (!drop_author || is_game) { if (!drop_author || is_game) {
m->via_bot_user_id = forwarded_message->via_bot_user_id; m->via_bot_user_id = forwarded_message->via_bot_user_id;
@ -28346,9 +28336,20 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
continue; continue;
} }
bool is_broken_server_copy = [&] {
switch (forwarded_message->content->get_type()) {
case MessageContentType::Poll:
return get_message_content_poll_is_closed(td_, forwarded_message->content.get()) ||
td_->auth_manager_->is_bot();
case MessageContentType::Dice:
return true;
default:
return false;
}
}();
bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy; bool need_copy = !message_id.is_server() || to_secret || copy_options[i].send_copy;
bool is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward && bool is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward && !is_broken_server_copy);
forwarded_message->content->get_type() != MessageContentType::Dice);
if (!(need_copy && td_->auth_manager_->is_bot()) && !can_save_message(from_dialog_id, forwarded_message)) { if (!(need_copy && td_->auth_manager_->is_bot()) && !can_save_message(from_dialog_id, forwarded_message)) {
LOG(INFO) << "Forward of " << message_id << " is restricted"; LOG(INFO) << "Forward of " << message_id << " is restricted";
continue; continue;
@ -31044,8 +31045,29 @@ void MessagesManager::check_send_message_result(int64 random_id, DialogId dialog
CHECK(source != nullptr); CHECK(source != nullptr);
auto sent_messages = UpdatesManager::get_new_messages(updates_ptr); auto sent_messages = UpdatesManager::get_new_messages(updates_ptr);
auto sent_messages_random_ids = UpdatesManager::get_sent_messages_random_ids(updates_ptr); auto sent_messages_random_ids = UpdatesManager::get_sent_messages_random_ids(updates_ptr);
auto is_invalid_poll_message = [](const telegram_api::Message *message) {
CHECK(message != nullptr);
auto constructor_id = message->get_id();
if (constructor_id == telegram_api::messageEmpty::ID) {
return true;
}
if (constructor_id != telegram_api::message::ID) {
return false;
}
auto media = static_cast<const telegram_api::message *>(message)->media_.get();
if (media == nullptr || media->get_id() != telegram_api::messageMediaPoll::ID) {
return false;
}
auto poll = static_cast<const telegram_api::messageMediaPoll *>(media)->poll_.get();
return !PollId(poll->id_).is_valid();
};
if (sent_messages.size() != 1u || sent_messages_random_ids.size() != 1u || if (sent_messages.size() != 1u || sent_messages_random_ids.size() != 1u ||
*sent_messages_random_ids.begin() != random_id || get_message_dialog_id(*sent_messages[0]) != dialog_id) { *sent_messages_random_ids.begin() != random_id || get_message_dialog_id(*sent_messages[0]) != dialog_id ||
is_invalid_poll_message(sent_messages[0]->get())) {
LOG(ERROR) << "Receive wrong result for sending message with random_id " << random_id << " from " << source LOG(ERROR) << "Receive wrong result for sending message with random_id " << random_id << " from " << source
<< " to " << dialog_id << ": " << oneline(to_string(*updates_ptr)); << " to " << dialog_id << ": " << oneline(to_string(*updates_ptr));
Dialog *d = get_dialog(dialog_id); Dialog *d = get_dialog(dialog_id);
@ -40250,9 +40272,8 @@ void MessagesManager::add_message_file_to_downloads(FullMessageId full_message_i
auto search_text = get_message_search_text(m); auto search_text = get_message_search_text(m);
auto file_source_id = get_message_file_source_id(full_message_id, true); auto file_source_id = get_message_file_source_id(full_message_id, true);
CHECK(file_source_id.is_valid()); CHECK(file_source_id.is_valid());
TRY_STATUS_PROMISE(promise, td_->download_manager_->add_file(file_id, file_source_id, std::move(search_text), send_closure(td_->download_manager_actor_, &DownloadManager::add_file, file_id, file_source_id,
static_cast<int8>(priority))); std::move(search_text), static_cast<int8>(priority), std::move(promise));
promise.set_value(td_->file_manager_->get_file_object(file_id));
} }
void MessagesManager::get_message_file_search_text(FullMessageId full_message_id, string unique_file_id, void MessagesManager::get_message_file_search_text(FullMessageId full_message_id, string unique_file_id,

View File

@ -267,11 +267,8 @@ void PollManager::tear_down() {
} }
PollManager::~PollManager() { PollManager::~PollManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), polls_); Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), polls_, server_poll_messages_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), server_poll_messages_); other_poll_messages_, poll_voters_, loaded_from_database_polls_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), other_poll_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), poll_voters_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), loaded_from_database_polls_);
} }
void PollManager::on_update_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int) { void PollManager::on_update_poll_timeout_callback(void *poll_manager_ptr, int64 poll_id_int) {
@ -1218,11 +1215,26 @@ void PollManager::do_stop_poll(PollId poll_id, FullMessageId full_message_id, un
bool is_inserted = being_closed_polls_.insert(poll_id).second; bool is_inserted = being_closed_polls_.insert(poll_id).second;
CHECK(is_inserted); CHECK(is_inserted);
auto new_promise = get_erase_log_event_promise(log_event_id, std::move(promise)); auto new_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), poll_id, log_event_id, promise = std::move(promise)](Result<Unit> result) mutable {
send_closure(actor_id, &PollManager::on_stop_poll_finished, poll_id, log_event_id, std::move(result),
std::move(promise));
});
td_->create_handler<StopPollQuery>(std::move(new_promise))->send(full_message_id, std::move(reply_markup), poll_id); td_->create_handler<StopPollQuery>(std::move(new_promise))->send(full_message_id, std::move(reply_markup), poll_id);
} }
void PollManager::on_stop_poll_finished(PollId poll_id, uint64 log_event_id, Result<Unit> &&result,
Promise<Unit> &&promise) {
being_closed_polls_.erase(poll_id);
if (log_event_id != 0 && !G()->close_flag()) {
binlog_erase(G()->td_db()->get_binlog(), log_event_id);
}
promise.set_result(std::move(result));
}
void PollManager::stop_local_poll(PollId poll_id) { void PollManager::stop_local_poll(PollId poll_id) {
CHECK(is_local_poll_id(poll_id)); CHECK(is_local_poll_id(poll_id));
auto poll = get_poll_editable(poll_id); auto poll = get_poll_editable(poll_id);

View File

@ -215,6 +215,8 @@ class PollManager final : public Actor {
void do_stop_poll(PollId poll_id, FullMessageId full_message_id, unique_ptr<ReplyMarkup> &&reply_markup, void do_stop_poll(PollId poll_id, FullMessageId full_message_id, unique_ptr<ReplyMarkup> &&reply_markup,
uint64 log_event_id, Promise<Unit> &&promise); uint64 log_event_id, Promise<Unit> &&promise);
void on_stop_poll_finished(PollId poll_id, uint64 log_event_id, Result<Unit> &&result, Promise<Unit> &&promise);
void forget_local_poll(PollId poll_id); void forget_local_poll(PollId poll_id);
MultiTimeout update_poll_timeout_{"UpdatePollTimeout"}; MultiTimeout update_poll_timeout_{"UpdatePollTimeout"};

View File

@ -221,13 +221,14 @@ static KeyboardButton get_keyboard_button(tl_object_ptr<telegram_api::KeyboardBu
} }
case telegram_api::keyboardButtonSimpleWebView::ID: { case telegram_api::keyboardButtonSimpleWebView::ID: {
auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonSimpleWebView>(keyboard_button_ptr); auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonSimpleWebView>(keyboard_button_ptr);
button.type = KeyboardButton::Type::WebView;
button.text = std::move(keyboard_button->text_);
auto r_url = LinkManager::check_link(keyboard_button->url_); auto r_url = LinkManager::check_link(keyboard_button->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
LOG(ERROR) << "Keyboard Web App " << r_url.error().message(); LOG(ERROR) << "Keyboard Web App " << r_url.error().message();
return {}; break;
} }
button.type = KeyboardButton::Type::WebView;
button.text = std::move(keyboard_button->text_);
button.url = r_url.move_as_ok(); button.url = r_url.move_as_ok();
break; break;
} }
@ -245,13 +246,13 @@ static InlineKeyboardButton get_inline_keyboard_button(
switch (keyboard_button_ptr->get_id()) { switch (keyboard_button_ptr->get_id()) {
case telegram_api::keyboardButtonUrl::ID: { case telegram_api::keyboardButtonUrl::ID: {
auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUrl>(keyboard_button_ptr); auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUrl>(keyboard_button_ptr);
button.type = InlineKeyboardButton::Type::Url;
button.text = std::move(keyboard_button->text_);
auto r_url = LinkManager::check_link(keyboard_button->url_); auto r_url = LinkManager::check_link(keyboard_button->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
LOG(ERROR) << "Inline keyboard " << r_url.error().message(); LOG(ERROR) << "Inline keyboard " << r_url.error().message();
return {}; break;
} }
button.type = InlineKeyboardButton::Type::Url;
button.text = std::move(keyboard_button->text_);
button.data = r_url.move_as_ok(); button.data = r_url.move_as_ok();
break; break;
} }
@ -286,38 +287,39 @@ static InlineKeyboardButton get_inline_keyboard_button(
} }
case telegram_api::keyboardButtonUrlAuth::ID: { case telegram_api::keyboardButtonUrlAuth::ID: {
auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUrlAuth>(keyboard_button_ptr); auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUrlAuth>(keyboard_button_ptr);
auto r_url = LinkManager::check_link(keyboard_button->url_);
if (r_url.is_error()) {
LOG(ERROR) << "Inline keyboard Login " << r_url.error().message();
break;
}
button.type = InlineKeyboardButton::Type::UrlAuth; button.type = InlineKeyboardButton::Type::UrlAuth;
button.id = keyboard_button->button_id_; button.id = keyboard_button->button_id_;
button.text = std::move(keyboard_button->text_); button.text = std::move(keyboard_button->text_);
button.forward_text = std::move(keyboard_button->fwd_text_); button.forward_text = std::move(keyboard_button->fwd_text_);
auto r_url = LinkManager::check_link(keyboard_button->url_);
if (r_url.is_error()) {
LOG(ERROR) << "Inline keyboard Login " << r_url.error().message();
return {};
}
button.data = r_url.move_as_ok(); button.data = r_url.move_as_ok();
break; break;
} }
case telegram_api::keyboardButtonUserProfile::ID: { case telegram_api::keyboardButtonUserProfile::ID: {
auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUserProfile>(keyboard_button_ptr); auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonUserProfile>(keyboard_button_ptr);
auto user_id = UserId(keyboard_button->user_id_);
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive " << user_id << " in inline keyboard";
break;
}
button.type = InlineKeyboardButton::Type::User; button.type = InlineKeyboardButton::Type::User;
button.text = std::move(keyboard_button->text_); button.text = std::move(keyboard_button->text_);
button.user_id = UserId(keyboard_button->user_id_); button.user_id = user_id;
if (!button.user_id.is_valid()) {
LOG(ERROR) << "Receive " << button.user_id << " in inline keyboard";
return {};
}
break; break;
} }
case telegram_api::keyboardButtonWebView::ID: { case telegram_api::keyboardButtonWebView::ID: {
auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonWebView>(keyboard_button_ptr); auto keyboard_button = move_tl_object_as<telegram_api::keyboardButtonWebView>(keyboard_button_ptr);
button.type = InlineKeyboardButton::Type::WebView;
button.text = std::move(keyboard_button->text_);
auto r_url = LinkManager::check_link(keyboard_button->url_); auto r_url = LinkManager::check_link(keyboard_button->url_);
if (r_url.is_error()) { if (r_url.is_error()) {
LOG(ERROR) << "Inline keyboard Web App " << r_url.error().message(); LOG(ERROR) << "Inline keyboard Web App " << r_url.error().message();
return {}; break;
} }
button.type = InlineKeyboardButton::Type::WebView;
button.text = std::move(keyboard_button->text_);
button.data = r_url.move_as_ok(); button.data = r_url.move_as_ok();
break; break;
} }

View File

@ -1305,18 +1305,10 @@ StickersManager::StickersManager(Td *td, ActorShared<> parent) : td_(td), parent
} }
StickersManager::~StickersManager() { StickersManager::~StickersManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), stickers_); Scheduler::instance()->destroy_on_scheduler(
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), sticker_sets_); G()->get_gc_scheduler_id(), stickers_, sticker_sets_, short_name_to_sticker_set_id_, attached_sticker_sets_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), short_name_to_sticker_set_id_); found_stickers_, found_sticker_sets_, emoji_language_codes_, emoji_language_code_versions_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), attached_sticker_sets_); emoji_language_code_last_difference_times_, reloaded_emoji_keywords_, dice_messages_, emoji_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_stickers_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_sticker_sets_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_language_codes_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_language_code_versions_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_language_code_last_difference_times_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), reloaded_emoji_keywords_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dice_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), emoji_messages_);
} }
void StickersManager::start_up() { void StickersManager::start_up() {

View File

@ -4003,6 +4003,10 @@ void Td::init_file_manager() {
explicit FileManagerContext(Td *td) : td_(td) { explicit FileManagerContext(Td *td) : td_(td) {
} }
bool need_notify_on_new_files() final {
return !td_->auth_manager_->is_bot();
}
void on_new_file(int64 size, int64 real_size, int32 cnt) final { void on_new_file(int64 size, int64 real_size, int32 cnt) final {
send_closure(G()->storage_manager(), &StorageManager::on_new_file, size, real_size, cnt); send_closure(G()->storage_manager(), &StorageManager::on_new_file, size, real_size, cnt);
} }
@ -4894,6 +4898,7 @@ void Td::on_request(uint64 id, td_api::getStorageStatistics &request) {
} }
void Td::on_request(uint64 id, td_api::getStorageStatisticsFast &request) { void Td::on_request(uint64 id, td_api::getStorageStatisticsFast &request) {
CHECK_IS_USER();
CREATE_REQUEST_PROMISE(); CREATE_REQUEST_PROMISE();
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<FileStatsFast> result) mutable { auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<FileStatsFast> result) mutable {
if (result.is_error()) { if (result.is_error()) {
@ -6691,23 +6696,26 @@ void Td::on_request(uint64 id, const td_api::addFileToDownloads &request) {
void Td::on_request(uint64 id, const td_api::toggleDownloadIsPaused &request) { void Td::on_request(uint64 id, const td_api::toggleDownloadIsPaused &request) {
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
promise.set_result(download_manager_->toggle_is_paused(FileId(request.file_id_, 0), request.is_paused_)); send_closure(download_manager_actor_, &DownloadManager::toggle_is_paused, FileId(request.file_id_, 0),
request.is_paused_, std::move(promise));
} }
void Td::on_request(uint64 id, const td_api::toggleAllDownloadsArePaused &request) { void Td::on_request(uint64 id, const td_api::toggleAllDownloadsArePaused &request) {
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
promise.set_result(download_manager_->toggle_all_is_paused(request.are_paused_)); send_closure(download_manager_actor_, &DownloadManager::toggle_all_is_paused, request.are_paused_,
std::move(promise));
} }
void Td::on_request(uint64 id, const td_api::removeFileFromDownloads &request) { void Td::on_request(uint64 id, const td_api::removeFileFromDownloads &request) {
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
promise.set_result(download_manager_->remove_file(FileId(request.file_id_, 0), {}, request.delete_from_cache_)); send_closure(download_manager_actor_, &DownloadManager::remove_file, FileId(request.file_id_, 0), FileSourceId(),
request.delete_from_cache_, std::move(promise));
} }
void Td::on_request(uint64 id, const td_api::removeAllFilesFromDownloads &request) { void Td::on_request(uint64 id, const td_api::removeAllFilesFromDownloads &request) {
CREATE_OK_REQUEST_PROMISE(); CREATE_OK_REQUEST_PROMISE();
promise.set_result( send_closure(download_manager_actor_, &DownloadManager::remove_all_files, request.only_active_,
download_manager_->remove_all_files(request.only_active_, request.only_completed_, request.delete_from_cache_)); request.only_completed_, request.delete_from_cache_, std::move(promise));
} }
void Td::on_request(uint64 id, td_api::searchFileDownloads &request) { void Td::on_request(uint64 id, td_api::searchFileDownloads &request) {

View File

@ -1617,7 +1617,7 @@ void UpdatesManager::after_get_difference() {
} }
} }
td_->download_manager_->after_get_difference(); send_closure(td_->download_manager_actor_, &DownloadManager::after_get_difference);
td_->inline_queries_manager_->after_get_difference(); td_->inline_queries_manager_->after_get_difference();
td_->messages_manager_->after_get_difference(); td_->messages_manager_->after_get_difference();
send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference); send_closure_later(td_->notification_manager_actor_, &NotificationManager::after_get_difference);

View File

@ -101,9 +101,8 @@ VoiceNotesManager::VoiceNotesManager(Td *td, ActorShared<> parent) : td_(td), pa
} }
VoiceNotesManager::~VoiceNotesManager() { VoiceNotesManager::~VoiceNotesManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_notes_); Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_notes_, voice_note_messages_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_note_messages_); message_voice_notes_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_voice_notes_);
} }
void VoiceNotesManager::tear_down() { void VoiceNotesManager::tear_down() {

View File

@ -418,11 +418,8 @@ void WebPagesManager::tear_down() {
} }
WebPagesManager::~WebPagesManager() { WebPagesManager::~WebPagesManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_pages_); Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_pages_, web_page_messages_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_page_messages_); got_web_page_previews_, url_to_web_page_id_, url_to_file_source_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), got_web_page_previews_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), url_to_web_page_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), url_to_file_source_id_);
} }
WebPageId WebPagesManager::on_get_web_page(tl_object_ptr<telegram_api::WebPage> &&web_page_ptr, WebPageId WebPagesManager::on_get_web_page(tl_object_ptr<telegram_api::WebPage> &&web_page_ptr,

View File

@ -841,14 +841,9 @@ void FileManager::init_actor() {
} }
FileManager::~FileManager() { FileManager::~FileManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), remote_location_info_); Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), remote_location_info_, file_hash_to_file_id_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_hash_to_file_id_); local_location_to_file_id_, generate_location_to_file_id_,
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), local_location_to_file_id_); pmc_id_to_file_node_id_, file_id_info_, empty_file_ids_, file_nodes_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), generate_location_to_file_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), pmc_id_to_file_node_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_id_info_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), empty_file_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_nodes_);
} }
string FileManager::fix_file_extension(Slice file_name, Slice file_type, Slice file_extension) { string FileManager::fix_file_extension(Slice file_name, Slice file_type, Slice file_extension) {
@ -2163,7 +2158,9 @@ void FileManager::delete_file(FileId file_id, Promise<Unit> promise, const char
if (file_view.has_local_location()) { if (file_view.has_local_location()) {
if (begins_with(file_view.local_location().path_, get_files_dir(file_view.get_type()))) { if (begins_with(file_view.local_location().path_, get_files_dir(file_view.get_type()))) {
clear_from_pmc(node); clear_from_pmc(node);
context_->on_new_file(-file_view.size(), -file_view.get_allocated_local_size(), -1); if (context_->need_notify_on_new_files()) {
context_->on_new_file(-file_view.size(), -file_view.get_allocated_local_size(), -1);
}
path = std::move(node->local_.full().path_); path = std::move(node->local_.full().path_);
} }
} else { } else {
@ -3517,7 +3514,7 @@ void FileManager::on_download_ok(QueryId query_id, FullLocalFileLocation local,
if (r_new_file_id.is_error()) { if (r_new_file_id.is_error()) {
status = Status::Error(PSLICE() << "Can't register local file after download: " << r_new_file_id.error().message()); status = Status::Error(PSLICE() << "Can't register local file after download: " << r_new_file_id.error().message());
} else { } else {
if (is_new) { if (is_new && context_->need_notify_on_new_files()) {
context_->on_new_file(size, get_file_view(r_new_file_id.ok()).get_allocated_local_size(), 1); context_->on_new_file(size, get_file_view(r_new_file_id.ok()).get_allocated_local_size(), 1);
} }
auto r_file_id = merge(r_new_file_id.ok(), file_id); auto r_file_id = merge(r_new_file_id.ok(), file_id);
@ -3690,8 +3687,10 @@ void FileManager::on_generate_ok(QueryId query_id, FullLocalFileLocation local)
CHECK(file_node); CHECK(file_node);
FileView file_view(file_node); FileView file_view(file_node);
if (!file_view.has_generate_location() || !begins_with(file_view.generate_location().conversion_, "#file_id#")) { if (context_->need_notify_on_new_files()) {
context_->on_new_file(file_view.size(), file_view.get_allocated_local_size(), 1); if (!file_view.has_generate_location() || !begins_with(file_view.generate_location().conversion_, "#file_id#")) {
context_->on_new_file(file_view.size(), file_view.get_allocated_local_size(), 1);
}
} }
run_upload(file_node, {}); run_upload(file_node, {});

View File

@ -384,6 +384,8 @@ class FileManager final : public FileLoadManager::Callback {
class Context { class Context {
public: public:
virtual bool need_notify_on_new_files() = 0;
virtual void on_new_file(int64 size, int64 real_size, int32 cnt) = 0; virtual void on_new_file(int64 size, int64 real_size, int32 cnt) = 0;
virtual void on_file_updated(FileId size) = 0; virtual void on_file_updated(FileId size) = 0;

View File

@ -105,6 +105,9 @@ class Scheduler {
template <class T> template <class T>
void destroy_on_scheduler(int32 sched_id, T &value); void destroy_on_scheduler(int32 sched_id, T &value);
template <class... ArgsT>
void destroy_on_scheduler(int32 sched_id, ArgsT &...values);
template <ActorSendType send_type, class EventT> template <ActorSendType send_type, class EventT>
void send_lambda(ActorRef actor_ref, EventT &&lambda); void send_lambda(ActorRef actor_ref, EventT &&lambda);

View File

@ -171,7 +171,7 @@ inline void Scheduler::send_to_scheduler(int32 sched_id, const ActorId<Actor> &a
} }
template <class T> template <class T>
inline void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) { void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) {
if (!value.empty()) { if (!value.empty()) {
destroy_on_scheduler_impl(sched_id, PromiseCreator::lambda([value = std::move(value)](Unit) { destroy_on_scheduler_impl(sched_id, PromiseCreator::lambda([value = std::move(value)](Unit) {
// destroy value // destroy value
@ -179,6 +179,13 @@ inline void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) {
} }
} }
template <class... ArgsT>
void Scheduler::destroy_on_scheduler(int32 sched_id, ArgsT &...values) {
destroy_on_scheduler_impl(sched_id, PromiseCreator::lambda([values = std::make_tuple(std::move(values)...)](Unit) {
// destroy values
}));
}
inline void Scheduler::before_tail_send(const ActorId<> &actor_id) { inline void Scheduler::before_tail_send(const ActorId<> &actor_id) {
// TODO // TODO
} }

View File

@ -253,7 +253,7 @@ class MainQueryActor final : public td::Actor {
} }
void wakeup() final { void wakeup() final {
int cnt = 100000; int cnt = 10000;
while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) { while (out_cnt_ < in_cnt_ + 100 && out_cnt_ < cnt) {
if (td::Random::fast_bool()) { if (td::Random::fast_bool()) {
send_closure(rand_elem(actors_), &QueryActor::query, create_query()); send_closure(rand_elem(actors_), &QueryActor::query, create_query());
@ -294,7 +294,7 @@ class SimpleActor final : public td::Actor {
} }
void wakeup() final { void wakeup() final {
if (q_ == 100000) { if (q_ == 10000) {
td::Scheduler::instance()->finish(); td::Scheduler::instance()->finish();
stop(); stop();
return; return;

View File

@ -138,13 +138,13 @@ TEST(Actors, workers_big_query_nine_threads) {
} }
TEST(Actors, workers_small_query_one_thread) { TEST(Actors, workers_small_query_one_thread) {
test_workers(0, 10, 1000000, 1); test_workers(0, 10, 100000, 1);
} }
TEST(Actors, workers_small_query_two_threads) { TEST(Actors, workers_small_query_two_threads) {
test_workers(2, 10, 1000000, 1); test_workers(2, 10, 100000, 1);
} }
TEST(Actors, workers_small_query_nine_threads) { TEST(Actors, workers_small_query_nine_threads) {
test_workers(9, 10, 1000000, 1); test_workers(9, 10, 10000, 1);
} }

View File

@ -469,7 +469,8 @@ class FlatHashTableChunks {
struct ChunkIt { struct ChunkIt {
size_t chunk_i; size_t chunk_i;
size_t chunk_mask; size_t chunk_mask;
size_t shift{}; size_t shift;
size_t pos() const { size_t pos() const {
return chunk_i; return chunk_i;
} }
@ -482,7 +483,7 @@ class FlatHashTableChunks {
}; };
ChunkIt get_chunk_it(size_t chunk_i) { ChunkIt get_chunk_it(size_t chunk_i) {
return {chunk_i, chunks_.size() - 1}; return ChunkIt{chunk_i, chunks_.size() - 1, 0};
} }
HashInfo calc_hash(const KeyT &key) { HashInfo calc_hash(const KeyT &key) {

View File

@ -198,13 +198,8 @@ class FlatHashTable {
}; };
FlatHashTable() = default; FlatHashTable() = default;
FlatHashTable(const FlatHashTable &other) { FlatHashTable(const FlatHashTable &other) = delete;
assign(other); FlatHashTable &operator=(const FlatHashTable &other) = delete;
}
void operator=(const FlatHashTable &other) {
clear();
assign(other);
}
FlatHashTable(std::initializer_list<NodeT> nodes) { FlatHashTable(std::initializer_list<NodeT> nodes) {
if (nodes.size() == 0) { if (nodes.size() == 0) {
@ -249,9 +244,7 @@ class FlatHashTable {
other.drop(); other.drop();
} }
~FlatHashTable() { ~FlatHashTable() {
if (nodes_ != nullptr) { clear_nodes(nodes_);
clear_nodes(nodes_);
}
} }
void swap(FlatHashTable &other) noexcept { void swap(FlatHashTable &other) noexcept {
@ -433,30 +426,6 @@ class FlatHashTable {
begin_bucket_ = 0; begin_bucket_ = 0;
} }
void assign(const FlatHashTable &other) {
if (other.size() == 0) {
return;
}
resize(other.bucket_count());
auto other_nodes_end = other.nodes_ + other.bucket_count_;
for (const NodeT *other_node = other.nodes_; other_node != other_nodes_end; ++other_node) {
if (other_node->empty()) {
continue;
}
auto bucket = calc_bucket(other_node->key());
while (true) {
auto &node = nodes_[bucket];
if (node.empty()) {
node.copy_from(*other_node);
break;
}
next_bucket(bucket);
}
}
used_node_count_ = other.used_node_count_;
}
NodeT *begin_impl() { NodeT *begin_impl() {
if (empty()) { if (empty()) {
return nullptr; return nullptr;

View File

@ -54,7 +54,7 @@ struct MapNode {
DCHECK(empty()); DCHECK(empty());
DCHECK(!other.empty()); DCHECK(!other.empty());
first = std::move(other.first); first = std::move(other.first);
other.first = KeyT{}; other.first = KeyT();
new (&second) ValueT(std::move(other.second)); new (&second) ValueT(std::move(other.second));
other.second.~ValueT(); other.second.~ValueT();
} }

View File

@ -20,7 +20,7 @@ struct SetNode {
using public_type = const KeyT; using public_type = const KeyT;
using second_type = KeyT; // TODO: remove second_type? using second_type = KeyT; // TODO: remove second_type?
KeyT first{}; KeyT first;
const KeyT &key() const { const KeyT &key() const {
return first; return first;
@ -30,7 +30,8 @@ struct SetNode {
return first; return first;
} }
SetNode() = default; SetNode(): first() {
}
explicit SetNode(KeyT key) : first(std::move(key)) { explicit SetNode(KeyT key) : first(std::move(key)) {
} }
SetNode(const SetNode &other) = delete; SetNode(const SetNode &other) = delete;
@ -42,7 +43,7 @@ struct SetNode {
DCHECK(empty()); DCHECK(empty());
DCHECK(!other.empty()); DCHECK(!other.empty());
first = std::move(other.first); first = std::move(other.first);
other.first = KeyT{}; other.first = KeyT();
} }
~SetNode() = default; ~SetNode() = default;
@ -71,7 +72,7 @@ struct SetNode<KeyT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void
struct Impl { struct Impl {
using second_type = KeyT; using second_type = KeyT;
KeyT first{}; KeyT first;
template <class InputKeyT> template <class InputKeyT>
explicit Impl(InputKeyT &&key) : first(std::forward<InputKeyT>(key)) { explicit Impl(InputKeyT &&key) : first(std::forward<InputKeyT>(key)) {
@ -99,7 +100,7 @@ struct SetNode<KeyT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void
return impl_->first; return impl_->first;
} }
SetNode() { SetNode(): impl_() {
} }
explicit SetNode(KeyT key) : impl_(td::make_unique<Impl>(std::move(key))) { explicit SetNode(KeyT key) : impl_(td::make_unique<Impl>(std::move(key))) {
} }

View File

@ -124,7 +124,6 @@ TEST(FlatHashMap, basic) {
ASSERT_EQ(2, kv.second); ASSERT_EQ(2, kv.second);
} }
map.erase(map.find(1)); map.erase(map.find(1));
auto map_copy = map;
} }
td::FlatHashMap<int, std::array<td::unique_ptr<td::string>, 10>> x; td::FlatHashMap<int, std::array<td::unique_ptr<td::string>, 10>> x;
@ -159,9 +158,6 @@ TEST(FlatHashMap, basic) {
} }
ASSERT_EQ(data, extract_kv(kv)); ASSERT_EQ(data, extract_kv(kv));
KV copied_kv(kv);
ASSERT_EQ(data, extract_kv(copied_kv));
KV moved_kv(std::move(kv)); KV moved_kv(std::move(kv));
ASSERT_EQ(data, extract_kv(moved_kv)); ASSERT_EQ(data, extract_kv(moved_kv));
ASSERT_EQ(Data{}, extract_kv(kv)); ASSERT_EQ(Data{}, extract_kv(kv));
@ -169,10 +165,6 @@ TEST(FlatHashMap, basic) {
kv = std::move(moved_kv); kv = std::move(moved_kv);
ASSERT_EQ(data, extract_kv(kv)); ASSERT_EQ(data, extract_kv(kv));
KV assign_copied_kv;
assign_copied_kv = kv;
ASSERT_EQ(data, extract_kv(assign_copied_kv));
KV assign_moved_kv; KV assign_moved_kv;
assign_moved_kv = std::move(kv); assign_moved_kv = std::move(kv);
ASSERT_EQ(data, extract_kv(assign_moved_kv)); ASSERT_EQ(data, extract_kv(assign_moved_kv));

View File

@ -377,7 +377,7 @@ TEST(DB, key_value) {
values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10))); values.push_back(td::rand_string('a', 'b', td::Random::fast(1, 10)));
} }
int queries_n = 3000; int queries_n = 1000;
td::vector<DbQuery> queries(queries_n); td::vector<DbQuery> queries(queries_n);
for (auto &q : queries) { for (auto &q : queries) {
int op = td::Random::fast(0, 2); int op = td::Random::fast(0, 2);
@ -427,7 +427,7 @@ TEST(DB, key_value) {
ASSERT_EQ(a.value, c.value); ASSERT_EQ(a.value, c.value);
ASSERT_EQ(a.value, d.value); ASSERT_EQ(a.value, d.value);
ASSERT_EQ(a.value, e.value); ASSERT_EQ(a.value, e.value);
if (cnt++ % 500 == 0) { if (cnt++ % 200 == 0) {
new_kv.impl().init(new_kv_name.str()).ensure(); new_kv.impl().init(new_kv_name.str()).ensure();
} }
} }