diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3230a9677..16d877a61 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -3981,11 +3981,12 @@ void Td::init_managers() { send_closure(G()->td(), &Td::send_update, counters.get_update_file_downloads_object()); } void start_file(FileId file_id, int8 priority) final { - send_closure(G()->file_manager(), &FileManager::download, file_id, make_download_file_callback(), priority, -1, - -1); + send_closure(G()->file_manager(), &FileManager::download, file_id, make_download_file_callback(), 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, -1, -1); + send_closure(G()->file_manager(), &FileManager::download, file_id, nullptr, 0, FileManager::KEEP_DOWNLOAD_OFFSET, + FileManager::KEEP_DOWNLOAD_LIMIT); } void delete_file(FileId file_id) final { send_closure( @@ -6506,7 +6507,8 @@ void Td::on_request(uint64 id, const td_api::getFileDownloadedPrefixSize &reques } void Td::on_request(uint64 id, const td_api::cancelDownloadFile &request) { - file_manager_->download(FileId(request.file_id_, 0), nullptr, request.only_if_pending_ ? -1 : 0, -1, -1); + file_manager_->download(FileId(request.file_id_, 0), nullptr, request.only_if_pending_ ? -1 : 0, + FileManager::KEEP_DOWNLOAD_OFFSET, FileManager::KEEP_DOWNLOAD_LIMIT); send_closure(actor_id(this), &Td::send_result, id, make_tl_object()); } diff --git a/td/telegram/files/FileGenerateManager.cpp b/td/telegram/files/FileGenerateManager.cpp index b0fe2e5d2..accea6aad 100644 --- a/td/telegram/files/FileGenerateManager.cpp +++ b/td/telegram/files/FileGenerateManager.cpp @@ -83,10 +83,11 @@ class FileDownloadGenerateActor final : public FileGenerateActor { }; send_closure(G()->file_manager(), &FileManager::download, file_id_, std::make_shared(actor_id(this)), 1, - -1, -1); + FileManager::KEEP_DOWNLOAD_OFFSET, FileManager::KEEP_DOWNLOAD_LIMIT); } void hangup() final { - send_closure(G()->file_manager(), &FileManager::download, file_id_, nullptr, 0, -1, -1); + send_closure(G()->file_manager(), &FileManager::download, file_id_, nullptr, 0, FileManager::KEEP_DOWNLOAD_OFFSET, + FileManager::KEEP_DOWNLOAD_LIMIT); stop(); } diff --git a/td/telegram/files/FileManager.cpp b/td/telegram/files/FileManager.cpp index 95b731bfa..0bfeceaf9 100644 --- a/td/telegram/files/FileManager.cpp +++ b/td/telegram/files/FileManager.cpp @@ -180,6 +180,7 @@ void FileNode::init_ready_size() { void FileNode::set_download_offset(int64 download_offset) { if (download_offset < 0 || download_offset > MAX_FILE_SIZE) { + // KEEP_DOWNLOAD_OFFSET is handled here return; } if (download_offset == download_offset_) { @@ -193,20 +194,44 @@ void FileNode::set_download_offset(int64 download_offset) { recalc_ready_prefix_size(-1, -1); on_info_changed(); } -void FileNode::set_download_limit(int64 download_limit) { - if (download_limit < 0) { - return; + +int64 FileNode::get_download_limit() const { + if (ignore_download_limit_) { + return 0; } - if (download_limit == download_limit_) { + return private_download_limit_; +} + +void FileNode::update_effective_download_limit(int64 old_download_limit) { + if (get_download_limit() == old_download_limit) { return; } - VLOG(update_file) << "File " << main_file_id_ << " has changed download_limit from " << download_limit_ << " to " - << download_limit; - download_limit_ = download_limit; + // Should be no false positives here + // When we use IGNORE_DOWNLOAD_LIMIT, set_download_limit will be ignored + // And in case we turn off ignore_download_limit, set_download_limit will not change effective downoad limit + VLOG(update_file) << "File " << main_file_id_ << " has changed download_limit from " << old_download_limit << " to " + << get_download_limit() << " (limit=" << private_download_limit_ + << ";ignore=" << ignore_download_limit_ << ")"; is_download_limit_dirty_ = true; } +void FileNode::set_download_limit(int64 download_limit) { + if (download_limit < 0) { + // KEEP_DOWNLOAD_LIMIT is handled here + return; + } + auto old_download_limit = get_download_limit(); + private_download_limit_ = download_limit; + update_effective_download_limit(old_download_limit); +} + +void FileNode::set_ignore_download_limit(bool ignore_download_limit) { + auto old_download_limit = get_download_limit(); + ignore_download_limit_ = ignore_download_limit; + update_effective_download_limit(old_download_limit); +} + void FileNode::drop_local_location() { set_local_location(LocalFileLocation(), 0, -1, -1); } @@ -2203,6 +2228,7 @@ void FileManager::download(FileId file_id, std::shared_ptr cal CHECK(new_priority == 0); file_info->download_callback_->on_download_error(file_id, Status::Error(200, "Canceled")); } + file_info->ignore_download_limit = limit == IGNORE_DOWNLOAD_LIMIT; file_info->download_priority_ = narrow_cast(new_priority); file_info->download_callback_ = std::move(callback); @@ -2219,11 +2245,13 @@ void FileManager::download(FileId file_id, std::shared_ptr cal void FileManager::run_download(FileNodePtr node, bool force_update_priority) { int8 priority = 0; + bool ignore_download_limit = false; for (auto id : node->file_ids_) { auto *info = get_file_id_info(id); if (info->download_priority_ > priority) { priority = info->download_priority_; } + ignore_download_limit |= info->ignore_download_limit; } auto old_priority = node->download_priority_; @@ -2251,6 +2279,7 @@ void FileManager::run_download(FileNodePtr node, bool force_update_priority) { return; } node->set_download_priority(priority); + node->set_ignore_download_limit(ignore_download_limit); bool need_update_offset = node->is_download_offset_dirty_; node->is_download_offset_dirty_ = false; @@ -2265,7 +2294,7 @@ void FileManager::run_download(FileNodePtr node, bool force_update_priority) { } if (need_update_limit || need_update_offset) { auto download_offset = node->download_offset_; - auto download_limit = node->download_limit_; + auto download_limit = node->get_download_limit(); if (file_view.is_encrypted_any()) { CHECK(download_offset <= MAX_FILE_SIZE); CHECK(download_limit <= std::numeric_limits::max()); @@ -2334,7 +2363,7 @@ void FileManager::run_download(FileNodePtr node, bool force_update_priority) { << node->remote_.full.value() << " with suggested name " << node->suggested_path() << " and encyption key " << node->encryption_key_; auto download_offset = node->download_offset_; - auto download_limit = node->download_limit_; + auto download_limit = node->get_download_limit(); if (file_view.is_encrypted_any()) { CHECK(download_offset <= MAX_FILE_SIZE); CHECK(download_limit <= std::numeric_limits::max()); diff --git a/td/telegram/files/FileManager.h b/td/telegram/files/FileManager.h index b57b390e2..956fc9e81 100644 --- a/td/telegram/files/FileManager.h +++ b/td/telegram/files/FileManager.h @@ -105,6 +105,7 @@ class FileNode { void set_download_offset(int64 download_offset); void set_download_limit(int64 download_limit); + void set_ignore_download_limit(bool ignore_download_limit); void on_changed(); void on_info_changed(); @@ -116,6 +117,8 @@ class FileNode { void on_pmc_flushed(); void on_info_flushed(); + int64 get_download_limit() const; + string suggested_path() const; private: @@ -129,7 +132,7 @@ class FileNode { LocalFileLocation local_; FileLoadManager::QueryId upload_id_ = 0; int64 download_offset_ = 0; - int64 download_limit_ = 0; + int64 private_download_limit_ = 0; int64 local_ready_size_ = 0; // PartialLocal only int64 local_ready_prefix_size_ = 0; // PartialLocal only @@ -184,9 +187,12 @@ class FileNode { bool upload_prefer_small_{false}; + bool ignore_download_limit_{false}; + void init_ready_size(); void recalc_ready_prefix_size(int64 prefix_offset, int64 ready_prefix_size); + void update_effective_download_limit(int64 old_download_limit); }; class FileManager; @@ -342,6 +348,9 @@ class FileView { class FileManager final : public FileLoadManager::Callback { public: + static constexpr int64 KEEP_DOWNLOAD_LIMIT = -1; + static constexpr int64 KEEP_DOWNLOAD_OFFSET = -1; + static constexpr int64 IGNORE_DOWNLOAD_LIMIT = -2; class DownloadCallback { public: DownloadCallback() = default; @@ -534,6 +543,7 @@ class FileManager final : public FileLoadManager::Callback { bool send_updates_flag_{false}; bool pin_flag_{false}; bool sent_file_id_flag_{false}; + bool ignore_download_limit{false}; int8 download_priority_{0}; int8 upload_priority_{0};