From 52abb9c5d5d38079d7f39af4616d5c687d0ddad8 Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Tue, 1 Mar 2022 15:34:51 +0100 Subject: [PATCH] DownloadManager create unique callback for each download --- td/telegram/DownloadManager.cpp | 13 +++++-- td/telegram/DownloadManager.h | 2 +- td/telegram/Td.cpp | 57 +++++++++++++++---------------- td/telegram/files/FileManager.cpp | 3 ++ 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/td/telegram/DownloadManager.cpp b/td/telegram/DownloadManager.cpp index fcdbc03c6..44cf31738 100644 --- a/td/telegram/DownloadManager.cpp +++ b/td/telegram/DownloadManager.cpp @@ -221,11 +221,14 @@ class DownloadManagerImpl final : public DownloadManager { return; } auto &file_info = *r_file_info_ptr.ok(); + if (file_info.link_token != get_link_token()) { + LOG(INFO) << "Ignore update_file_download_state because of outdated link_token"; + } with_file_info(file_info, [&](FileInfo &file_info) { file_info.size = size; file_info.downloaded_size = download_size; - if (file_info.is_paused != is_paused) { + if (is_paused && file_info.is_paused != is_paused) { file_info.is_paused = is_paused; file_info.need_save_to_db = true; } @@ -259,6 +262,7 @@ class DownloadManagerImpl final : public DownloadManager { int64 downloaded_size{}; int32 created_at{}; int32 completed_at{}; + uint64 link_token{}; }; FlatHashMap by_file_id_; @@ -272,6 +276,7 @@ class DownloadManagerImpl final : public DownloadManager { bool is_synchonized_{false}; bool is_started_{false}; int64 max_download_id_{0}; + uint64 last_link_token_{0}; int64 next_download_id() { return ++max_download_id_; @@ -389,13 +394,14 @@ class DownloadManagerImpl final : public DownloadManager { by_internal_file_id_[file_info->internal_file_id] = download_id; by_file_id_[file_info->file_id] = download_id; hints_.add(download_id, search_text.empty() ? string(" ") : search_text); + file_info->link_token = ++last_link_token_; LOG(INFO) << "Adding to downloads file " << file_info->file_id << '/' << file_info->internal_file_id << " with is_paused = " << file_info->is_paused; auto it = files_.emplace(download_id, std::move(file_info)).first; register_file_info(*it->second); if (it->second->completed_at == 0) { - callback_->start_file(it->second->internal_file_id, it->second->priority); + callback_->start_file(it->second->internal_file_id, it->second->priority, it->second->link_token); } } @@ -419,11 +425,12 @@ class DownloadManagerImpl final : public DownloadManager { with_file_info(file_info, [&](auto &file_info) { file_info.is_paused = is_paused; file_info.need_save_to_db = true; + file_info.link_token = ++last_link_token_; }); if (is_paused) { callback_->pause_file(file_info.internal_file_id); } else { - callback_->start_file(file_info.internal_file_id, file_info.priority); + callback_->start_file(file_info.internal_file_id, file_info.priority, file_info.link_token); } } diff --git a/td/telegram/DownloadManager.h b/td/telegram/DownloadManager.h index 56a825f93..647d44182 100644 --- a/td/telegram/DownloadManager.h +++ b/td/telegram/DownloadManager.h @@ -49,7 +49,7 @@ class DownloadManager : public Actor { virtual ~Callback() = default; virtual void update_counters(Counters counters) = 0; virtual void update_file_removed(FileId file_id) = 0; - virtual void start_file(FileId file_id, int8 priority) = 0; + virtual void start_file(FileId file_id, int8 priority, uint64 link_token) = 0; virtual void pause_file(FileId file_id) = 0; virtual void delete_file(FileId file_id) = 0; virtual FileId dup_file_id(FileId file_id) = 0; diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 7610e99cd..2c9688857 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3984,9 +3984,9 @@ void Td::init_managers() { send_closure(G()->td(), &Td::send_update, td_api::make_object(file_id.get())); } - void start_file(FileId file_id, int8 priority) final { - send_closure(G()->file_manager(), &FileManager::download, file_id, make_download_file_callback(), priority, - FileManager::KEEP_DOWNLOAD_OFFSET, FileManager::IGNORE_DOWNLOAD_LIMIT); + void start_file(FileId file_id, int8 priority, uint64 link_token) final { + send_closure(G()->file_manager(), &FileManager::download, file_id, make_download_file_callback(link_token), + priority, FileManager::KEEP_DOWNLOAD_OFFSET, FileManager::IGNORE_DOWNLOAD_LIMIT); } void pause_file(FileId file_id) final { send_closure(G()->file_manager(), &FileManager::download, file_id, nullptr, 0, FileManager::KEEP_DOWNLOAD_OFFSET, @@ -4016,33 +4016,32 @@ void Td::init_managers() { private: ActorShared<> parent_; ActorId download_manager_; - std::shared_ptr download_file_callback_; - std::shared_ptr make_download_file_callback() { - if (!download_file_callback_) { - class Impl final : public FileManager::DownloadCallback { - public: - explicit Impl(ActorId download_manager) : download_manager_(download_manager) { - } - void on_progress(FileId file_id) final { - auto td = G()->td().get_actor_unsafe(); - auto file_view = td->file_manager_->get_file_view(file_id); - send_closure(download_manager_, &DownloadManager::update_file_download_state, file_id, - file_view.local_total_size(), file_view.expected_size(), !file_view.is_downloading()); - // TODO: handle deleted state? - } - void on_download_ok(FileId file_id) final { - on_progress(file_id); - } - void on_download_error(FileId file_id, Status error) { - on_progress(file_id); - } + std::shared_ptr make_download_file_callback(uint64 link_token) { + class Impl final : public FileManager::DownloadCallback { + public: + explicit Impl(ActorShared download_manager) : download_manager_(std::move(download_manager)) { + } + void on_progress(FileId file_id) final { + send_update(file_id, false); + } + void on_download_ok(FileId file_id) final { + send_update(file_id, true); + } + void on_download_error(FileId file_id, Status error) { + send_update(file_id, true); + } - private: - ActorId download_manager_; - }; - download_file_callback_ = std::make_shared(download_manager_); - } - return download_file_callback_; + private: + ActorShared download_manager_; + void send_update(FileId file_id, bool is_paused) { + auto td = G()->td().get_actor_unsafe(); + auto file_view = td->file_manager_->get_file_view(file_id); + send_closure(download_manager_, &DownloadManager::update_file_download_state, file_id, + file_view.local_total_size(), file_view.size(), is_paused); + // TODO: handle deleted state? + } + }; + return std::make_shared(ActorShared(download_manager_, link_token)); } }; send_closure_later(download_manager_actor_, &DownloadManager::set_callback, diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index c48428f6b..a31afaf20 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -3915,5 +3915,8 @@ void FileManager::hangup() { void FileManager::tear_down() { parent_.reset(); } +constexpr int64 FileManager::KEEP_DOWNLOAD_LIMIT; +constexpr int64 FileManager::KEEP_DOWNLOAD_OFFSET; +constexpr int64 FileManager::IGNORE_DOWNLOAD_LIMIT; } // namespace td