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
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")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl")
if (ILLUMOS)

View File

@ -3399,43 +3399,16 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent
}
ContactsManager::~ContactsManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), users_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), users_full_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_photos_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_users_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), pending_user_photos_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), user_profile_photo_file_source_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), my_photo_file_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chats_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), chats_full_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), unknown_chats_);
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_);
Scheduler::instance()->destroy_on_scheduler(
G()->get_gc_scheduler_id(), users_, users_full_, user_photos_, unknown_users_, pending_user_photos_,
user_profile_photo_file_source_ids_, my_photo_file_id_, chats_, chats_full_, unknown_chats_,
chat_full_file_source_ids_, min_channels_, channels_, channels_full_, unknown_channels_,
invalidated_channels_full_, channel_full_file_source_ids_, secret_chats_, unknown_secret_chats_,
secret_chats_with_user_, invite_link_infos_, dialog_access_by_invite_link_, loaded_from_database_users_,
unavailable_user_fulls_, loaded_from_database_chats_, unavailable_chat_fulls_, loaded_from_database_channels_,
unavailable_channel_fulls_, loaded_from_database_secret_chats_, dialog_administrators_,
cached_channel_participants_, resolved_phone_numbers_, channel_participants_, all_imported_contacts_,
linked_channel_ids_, restricted_user_ids_, restricted_channel_ids_);
}
void ContactsManager::tear_down() {
@ -8795,23 +8768,24 @@ void ContactsManager::on_get_user(tl_object_ptr<telegram_api::User> &&user_ptr,
class ContactsManager::UserLogEvent {
public:
UserId user_id;
User u;
const User *u_in = nullptr;
unique_ptr<User> u_out;
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>
void store(StorerT &storer) const {
td::store(user_id, storer);
td::store(u, storer);
td::store(*u_in, storer);
}
template <class ParserT>
void parse(ParserT &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)));
}
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);
if (u->log_event_id == 0) {
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";
User *u = add_user(user_id, "on_binlog_user_event");
*u = std::move(log_event.u); // users come from binlog before all other events, so just add them
User *u = users_.emplace(user_id, std::move(log_event.u_out)).first->second.get();
CHECK(u != nullptr);
u->log_event_id = event.id_;
@ -9109,23 +9083,24 @@ ContactsManager::User *ContactsManager::get_user_force_impl(UserId user_id) {
class ContactsManager::ChatLogEvent {
public:
ChatId chat_id;
Chat c;
const Chat *c_in = nullptr;
unique_ptr<Chat> c_out;
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>
void store(StorerT &storer) const {
td::store(chat_id, storer);
td::store(c, storer);
td::store(*c_in, storer);
}
template <class ParserT>
void parse(ParserT &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);
if (!c->is_saved) {
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);
if (c->log_event_id == 0) {
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";
Chat *c = add_chat(chat_id);
*c = std::move(log_event.c); // chats come from binlog before all other events, so just add them
Chat *c = chats_.emplace(chat_id, std::move(log_event.c_out)).first->second.get();
CHECK(c != nullptr);
c->log_event_id = event.id_;
@ -9346,23 +9321,24 @@ ContactsManager::Chat *ContactsManager::get_chat_force(ChatId chat_id) {
class ContactsManager::ChannelLogEvent {
public:
ChannelId channel_id;
Channel c;
const Channel *c_in = nullptr;
unique_ptr<Channel> c_out;
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>
void store(StorerT &storer) const {
td::store(channel_id, storer);
td::store(c, storer);
td::store(*c_in, storer);
}
template <class ParserT>
void parse(ParserT &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)));
}
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);
if (c->log_event_id == 0) {
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";
Channel *c = add_channel(channel_id, "on_binlog_channel_event");
*c = std::move(log_event.c); // channels come from binlog before all other events, so just add them
Channel *c = channels_.emplace(channel_id, std::move(log_event.c_out)).first->second.get();
CHECK(c != nullptr);
c->log_event_id = event.id_;
@ -9607,23 +9583,24 @@ ContactsManager::Channel *ContactsManager::get_channel_force(ChannelId channel_i
class ContactsManager::SecretChatLogEvent {
public:
SecretChatId secret_chat_id;
SecretChat c;
const SecretChat *c_in = nullptr;
unique_ptr<SecretChat> c_out;
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>
void store(StorerT &storer) const {
td::store(secret_chat_id, storer);
td::store(c, storer);
td::store(*c_in, storer);
}
template <class ParserT>
void parse(ParserT &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);
if (!c->is_saved) {
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);
if (c->log_event_id == 0) {
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";
SecretChat *c = add_secret_chat(secret_chat_id);
*c = std::move(log_event.c); // secret chats come from binlog before all other events, so just add them
SecretChat *c = secret_chats_.emplace(secret_chat_id, std::move(log_event.c_out)).first->second.get();
CHECK(c != nullptr);
c->log_event_id = event.id_;

View File

@ -6,7 +6,6 @@
//
#include "td/telegram/DownloadManager.h"
#include "td/telegram/FileReferenceManager.h"
#include "td/telegram/files/FileId.hpp"
#include "td/telegram/files/FileSourceId.hpp"
#include "td/telegram/Global.h"
@ -83,64 +82,43 @@ class DownloadManagerImpl final : public DownloadManager {
load_database_files();
}
Status toggle_is_paused(FileId file_id, bool is_paused) final {
TRY_STATUS(check_is_active());
TRY_RESULT(file_info_ptr, get_file_info(file_id));
void toggle_is_paused(FileId file_id, bool is_paused, Promise<Unit> promise) final {
TRY_STATUS_PROMISE(promise, check_is_active());
TRY_RESULT_PROMISE(promise, file_info_ptr, get_file_info(file_id));
toggle_is_paused(*file_info_ptr, is_paused);
return Status::OK();
promise.set_value(Unit());
}
Status toggle_all_is_paused(bool is_paused) final {
TRY_STATUS(check_is_active());
void toggle_all_is_paused(bool is_paused, Promise<Unit> promise) final {
TRY_STATUS_PROMISE(promise, check_is_active());
vector<FileId> to_toggle;
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 {
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();
void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache, Promise<Unit> promise) final {
promise.set_result(remove_file_impl(file_id, file_source_id, delete_from_cache));
}
Status remove_file_if_finished(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(file_id, {}, false);
void remove_file_if_finished(FileId file_id) final {
remove_file_if_finished_impl(file_id).ignore();
}
Status remove_all_files(bool only_active, bool only_completed, bool delete_from_cache) final {
TRY_STATUS(check_is_active());
void remove_all_files(bool only_active, bool only_completed, bool delete_from_cache, Promise<Unit> promise) final {
TRY_STATUS_PROMISE(promise, check_is_active());
vector<FileId> to_remove;
for (auto &it : files_) {
FileInfo &file_info = *it.second;
@ -153,15 +131,16 @@ class DownloadManagerImpl final : public DownloadManager {
to_remove.push_back(file_info.file_id);
}
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 {
TRY_STATUS(check_is_active());
void add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority,
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();
@ -176,19 +155,23 @@ class DownloadManagerImpl final : public DownloadManager {
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_) {
return Status::OK();
return;
}
TRY_STATUS(check_is_active());
TRY_RESULT(file_info_ptr, get_file_info(file_id, file_source_id));
auto &file_info = *file_info_ptr;
if (check_is_active().is_error()) {
return;
}
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);
return Status::OK();
}
void hints_synchronized(Result<Unit>) {
@ -328,7 +311,7 @@ class DownloadManagerImpl final : public DownloadManager {
return;
}
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 {
@ -376,6 +359,7 @@ class DownloadManagerImpl final : public DownloadManager {
Counters sent_counters_;
FileCounters file_counters_;
bool is_inited_{false};
bool is_database_being_loaded_{false};
bool is_database_loaded_{false};
bool is_search_inited_{false};
int64 max_download_id_{0};
@ -488,6 +472,8 @@ class DownloadManagerImpl final : public DownloadManager {
return;
}
CHECK(is_inited_);
CHECK(!is_database_being_loaded_);
is_database_being_loaded_ = true;
LOG(INFO) << "Start Download Manager database loading";
@ -503,6 +489,7 @@ class DownloadManagerImpl final : public DownloadManager {
}
is_database_loaded_ = true;
is_database_being_loaded_ = false;
update_counters();
check_completed_downloads_size();
@ -512,13 +499,13 @@ class DownloadManagerImpl final : public DownloadManager {
void prepare_hints() {
for (auto &it : files_) {
const auto &file_info = *it.second;
send_closure(G()->file_reference_manager(), &FileReferenceManager::get_file_search_text, file_info.file_source_id,
callback_->get_file_view(file_info.file_id).get_unique_file_id(),
[actor_id = actor_id(this), promise = load_search_text_multipromise_.get_promise(),
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), std::move(promise));
});
auto promise =
PromiseCreator::lambda([actor_id = actor_id(this), promise = load_search_text_multipromise_.get_promise(),
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),
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 (!G()->close_flag()) {
remove_file(it->second->file_id, {}, false);
remove_file_impl(it->second->file_id, {}, false);
}
} else {
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
<< " with downloaded_size = " << file_info->downloaded_size
<< " and is_paused = " << file_info->is_paused;
auto res = files_.emplace(download_id, std::move(file_info));
auto it = res.first;
auto it = files_.emplace(download_id, std::move(file_info)).first;
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
if (is_completed(*it->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 {
clear_counters();
}
@ -756,7 +779,7 @@ class DownloadManagerImpl final : public DownloadManager {
while (completed_download_ids_.size() > MAX_COMPLETED_DOWNLOADS) {
auto download_id = *completed_download_ids_.begin();
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 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 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,
FileSourceId file_source_id,
int32 add_date, int32 complete_date,
@ -86,20 +88,23 @@ class DownloadManager : public Actor {
//
// public interface for user
//
virtual void after_get_difference() = 0;
virtual Status add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority) = 0;
virtual Status change_search_text(FileId file_id, FileSourceId file_source_id, string search_text) = 0;
virtual Status toggle_is_paused(FileId file_id, bool is_paused) = 0;
virtual Status toggle_all_is_paused(bool is_paused) = 0;
virtual void add_file(FileId file_id, FileSourceId file_source_id, string search_text, int8 priority,
Promise<td_api::object_ptr<td_api::file>> promise) = 0;
virtual void toggle_is_paused(FileId file_id, bool is_paused, Promise<Unit> promise) = 0;
virtual void toggle_all_is_paused(bool is_paused, Promise<Unit> promise) = 0;
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;
virtual Status remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache) = 0;
virtual Status remove_file_if_finished(FileId file_id) = 0;
virtual Status remove_all_files(bool only_active, bool only_completed, bool delete_from_cache) = 0;
virtual void remove_file(FileId file_id, FileSourceId file_source_id, bool delete_from_cache,
Promise<Unit> promise) = 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
//
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,
int64 expected_size, bool is_paused) = 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);
}
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) {
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);
}
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(
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(),

View File

@ -45,18 +45,22 @@ class DownloadManagerCallback final : public DownloadManager::Callback {
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;
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,
int32 add_date, int32 complete_date,
bool is_paused);
bool is_paused) final;
private:
Td *td_;
ActorShared<> parent_;
FileView get_file_view(FileId file_id);
static std::shared_ptr<FileManager::DownloadCallback> make_download_file_callback(
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"));
}
// resolve?phone=12345
return user_link;
return std::move(user_link);
}
} else if (path.size() == 1 && path[0] == "login") {
// 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"));
}
// /+<phone_number>
return user_link;
return std::move(user_link);
} else {
// /+<link>
return td::make_unique<InternalLinkDialogInvite>(PSTRING() << "tg:join?invite="

View File

@ -51,6 +51,7 @@
#include "td/telegram/NotificationSettingsManager.h"
#include "td/telegram/NotificationSound.h"
#include "td/telegram/NotificationType.h"
#include "td/telegram/PollId.h"
#include "td/telegram/PublicDialogType.h"
#include "td/telegram/ReplyMarkup.h"
#include "td/telegram/ReplyMarkup.hpp"
@ -5810,34 +5811,16 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent)
}
MessagesManager::~MessagesManager() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), ttl_nodes_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), ttl_heap_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), being_sent_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), update_message_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), update_scheduled_message_ids_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_id_to_dialog_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), last_clear_history_message_id_to_dialog_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), dialogs_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), postponed_chat_read_inbox_updates_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), found_public_dialogs_);
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_);
Scheduler::instance()->destroy_on_scheduler(
G()->get_gc_scheduler_id(), ttl_nodes_, ttl_heap_, being_sent_messages_, update_message_ids_,
update_scheduled_message_ids_, message_id_to_dialog_id_, last_clear_history_message_id_to_dialog_id_, dialogs_,
postponed_chat_read_inbox_updates_, found_public_dialogs_, found_on_server_dialogs_, found_common_dialogs_,
message_embedding_codes_[0], message_embedding_codes_[1], replied_by_media_timestamp_messages_,
notification_group_id_to_dialog_id_, active_get_channel_differencies_, get_channel_difference_to_log_event_id_,
channel_get_difference_retry_timeouts_, is_channel_difference_finished_, resolved_usernames_,
inaccessible_resolved_usernames_, dialog_bot_command_message_ids_, full_message_id_to_file_source_id_,
last_outgoing_forwarded_message_date_, dialog_viewed_messages_, dialog_online_member_counts_,
previous_repaired_read_inbox_max_message_id_);
}
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)) {
auto file_view = td_->file_manager_->get_file_view(file_id);
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) {
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(),
file_source_id, false);
file_source_id, false, Promise<Unit>());
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()) {
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(),
file_source_id, false);
file_source_id, false, Promise<Unit>());
}
}
}
@ -28032,8 +28016,8 @@ class MessagesManager::ForwardMessagesLogEvent {
DialogId from_dialog_id;
vector<MessageId> message_ids;
vector<Message *> messages_in;
bool drop_author = false;
bool drop_media_captions = false;
bool drop_author;
bool drop_media_captions;
vector<unique_ptr<Message>> messages_out;
template <class StorerT>
@ -28055,6 +28039,9 @@ class MessagesManager::ForwardMessagesLogEvent {
PARSE_FLAG(drop_author);
PARSE_FLAG(drop_media_captions);
END_PARSE_FLAGS();
} else {
drop_author = false;
drop_media_captions = false;
}
td::parse(to_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,
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;
if (!drop_author || is_game) {
m->via_bot_user_id = forwarded_message->via_bot_user_id;
@ -28346,9 +28336,20 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
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 is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward &&
forwarded_message->content->get_type() != MessageContentType::Dice);
bool is_local_copy = need_copy && !(message_id.is_server() && can_use_server_forward && !is_broken_server_copy);
if (!(need_copy && td_->auth_manager_->is_bot()) && !can_save_message(from_dialog_id, forwarded_message)) {
LOG(INFO) << "Forward of " << message_id << " is restricted";
continue;
@ -31044,8 +31045,29 @@ void MessagesManager::check_send_message_result(int64 random_id, DialogId dialog
CHECK(source != nullptr);
auto sent_messages = UpdatesManager::get_new_messages(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 ||
*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
<< " to " << dialog_id << ": " << oneline(to_string(*updates_ptr));
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 file_source_id = get_message_file_source_id(full_message_id, true);
CHECK(file_source_id.is_valid());
TRY_STATUS_PROMISE(promise, td_->download_manager_->add_file(file_id, file_source_id, std::move(search_text),
static_cast<int8>(priority)));
promise.set_value(td_->file_manager_->get_file_object(file_id));
send_closure(td_->download_manager_actor_, &DownloadManager::add_file, file_id, file_source_id,
std::move(search_text), static_cast<int8>(priority), std::move(promise));
}
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() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), polls_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), server_poll_messages_);
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_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), polls_, server_poll_messages_,
other_poll_messages_, poll_voters_, loaded_from_database_polls_);
}
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;
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);
}
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) {
CHECK(is_local_poll_id(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,
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);
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: {
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_);
if (r_url.is_error()) {
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();
break;
}
@ -245,13 +246,13 @@ static InlineKeyboardButton get_inline_keyboard_button(
switch (keyboard_button_ptr->get_id()) {
case telegram_api::keyboardButtonUrl::ID: {
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_);
if (r_url.is_error()) {
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();
break;
}
@ -286,38 +287,39 @@ static InlineKeyboardButton get_inline_keyboard_button(
}
case telegram_api::keyboardButtonUrlAuth::ID: {
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.id = keyboard_button->button_id_;
button.text = std::move(keyboard_button->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();
break;
}
case telegram_api::keyboardButtonUserProfile::ID: {
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.text = std::move(keyboard_button->text_);
button.user_id = UserId(keyboard_button->user_id_);
if (!button.user_id.is_valid()) {
LOG(ERROR) << "Receive " << button.user_id << " in inline keyboard";
return {};
}
button.user_id = user_id;
break;
}
case telegram_api::keyboardButtonWebView::ID: {
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_);
if (r_url.is_error()) {
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();
break;
}

View File

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

View File

@ -4003,6 +4003,10 @@ void Td::init_file_manager() {
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 {
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) {
CHECK_IS_USER();
CREATE_REQUEST_PROMISE();
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<FileStatsFast> result) mutable {
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) {
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) {
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) {
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) {
CREATE_OK_REQUEST_PROMISE();
promise.set_result(
download_manager_->remove_all_files(request.only_active_, request.only_completed_, request.delete_from_cache_));
send_closure(download_manager_actor_, &DownloadManager::remove_all_files, request.only_active_,
request.only_completed_, request.delete_from_cache_, std::move(promise));
}
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_->messages_manager_->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() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_notes_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_note_messages_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), message_voice_notes_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), voice_notes_, voice_note_messages_,
message_voice_notes_);
}
void VoiceNotesManager::tear_down() {

View File

@ -418,11 +418,8 @@ void WebPagesManager::tear_down() {
}
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_page_messages_);
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_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), web_pages_, web_page_messages_,
got_web_page_previews_, url_to_web_page_id_, url_to_file_source_id_);
}
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() {
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), remote_location_info_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), file_hash_to_file_id_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), local_location_to_file_id_);
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_);
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), remote_location_info_, file_hash_to_file_id_,
local_location_to_file_id_, generate_location_to_file_id_,
pmc_id_to_file_node_id_, file_id_info_, empty_file_ids_, file_nodes_);
}
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 (begins_with(file_view.local_location().path_, get_files_dir(file_view.get_type()))) {
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_);
}
} else {
@ -3517,7 +3514,7 @@ void FileManager::on_download_ok(QueryId query_id, FullLocalFileLocation local,
if (r_new_file_id.is_error()) {
status = Status::Error(PSLICE() << "Can't register local file after download: " << r_new_file_id.error().message());
} 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);
}
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);
FileView file_view(file_node);
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);
if (context_->need_notify_on_new_files()) {
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, {});

View File

@ -384,6 +384,8 @@ class FileManager final : public FileLoadManager::Callback {
class Context {
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_file_updated(FileId size) = 0;

View File

@ -105,6 +105,9 @@ class Scheduler {
template <class T>
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>
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>
inline void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) {
void Scheduler::destroy_on_scheduler(int32 sched_id, T &value) {
if (!value.empty()) {
destroy_on_scheduler_impl(sched_id, PromiseCreator::lambda([value = std::move(value)](Unit) {
// 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) {
// TODO
}

View File

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

View File

@ -138,13 +138,13 @@ TEST(Actors, workers_big_query_nine_threads) {
}
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_workers(2, 10, 1000000, 1);
test_workers(2, 10, 100000, 1);
}
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 {
size_t chunk_i;
size_t chunk_mask;
size_t shift{};
size_t shift;
size_t pos() const {
return chunk_i;
}
@ -482,7 +483,7 @@ class FlatHashTableChunks {
};
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) {

View File

@ -198,13 +198,8 @@ class FlatHashTable {
};
FlatHashTable() = default;
FlatHashTable(const FlatHashTable &other) {
assign(other);
}
void operator=(const FlatHashTable &other) {
clear();
assign(other);
}
FlatHashTable(const FlatHashTable &other) = delete;
FlatHashTable &operator=(const FlatHashTable &other) = delete;
FlatHashTable(std::initializer_list<NodeT> nodes) {
if (nodes.size() == 0) {
@ -249,9 +244,7 @@ class FlatHashTable {
other.drop();
}
~FlatHashTable() {
if (nodes_ != nullptr) {
clear_nodes(nodes_);
}
clear_nodes(nodes_);
}
void swap(FlatHashTable &other) noexcept {
@ -433,30 +426,6 @@ class FlatHashTable {
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() {
if (empty()) {
return nullptr;

View File

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

View File

@ -20,7 +20,7 @@ struct SetNode {
using public_type = const KeyT;
using second_type = KeyT; // TODO: remove second_type?
KeyT first{};
KeyT first;
const KeyT &key() const {
return first;
@ -30,7 +30,8 @@ struct SetNode {
return first;
}
SetNode() = default;
SetNode(): first() {
}
explicit SetNode(KeyT key) : first(std::move(key)) {
}
SetNode(const SetNode &other) = delete;
@ -42,7 +43,7 @@ struct SetNode {
DCHECK(empty());
DCHECK(!other.empty());
first = std::move(other.first);
other.first = KeyT{};
other.first = KeyT();
}
~SetNode() = default;
@ -71,7 +72,7 @@ struct SetNode<KeyT, typename std::enable_if_t<(sizeof(KeyT) > 28 * sizeof(void
struct Impl {
using second_type = KeyT;
KeyT first{};
KeyT first;
template <class InputKeyT>
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;
}
SetNode() {
SetNode(): impl_() {
}
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);
}
map.erase(map.find(1));
auto map_copy = map;
}
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));
KV copied_kv(kv);
ASSERT_EQ(data, extract_kv(copied_kv));
KV moved_kv(std::move(kv));
ASSERT_EQ(data, extract_kv(moved_kv));
ASSERT_EQ(Data{}, extract_kv(kv));
@ -169,10 +165,6 @@ TEST(FlatHashMap, basic) {
kv = std::move(moved_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;
assign_moved_kv = std::move(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)));
}
int queries_n = 3000;
int queries_n = 1000;
td::vector<DbQuery> queries(queries_n);
for (auto &q : queries) {
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, d.value);
ASSERT_EQ(a.value, e.value);
if (cnt++ % 500 == 0) {
if (cnt++ % 200 == 0) {
new_kv.impl().init(new_kv_name.str()).ensure();
}
}