1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8 
9 #include "td/telegram/DialogId.h"
10 #include "td/telegram/files/FileDbId.h"
11 #include "td/telegram/files/FileEncryptionKey.h"
12 #include "td/telegram/files/FileGenerateManager.h"
13 #include "td/telegram/files/FileId.h"
14 #include "td/telegram/files/FileLoadManager.h"
15 #include "td/telegram/files/FileLocation.h"
16 #include "td/telegram/files/FileSourceId.h"
17 #include "td/telegram/files/FileType.h"
18 #include "td/telegram/Location.h"
19 #include "td/telegram/PhotoSizeSource.h"
20 #include "td/telegram/td_api.h"
21 #include "td/telegram/telegram_api.h"
22 
23 #include "td/actor/actor.h"
24 #include "td/actor/PromiseFuture.h"
25 
26 #include "td/utils/buffer.h"
27 #include "td/utils/common.h"
28 #include "td/utils/Container.h"
29 #include "td/utils/Enumerator.h"
30 #include "td/utils/logging.h"
31 #include "td/utils/optional.h"
32 #include "td/utils/Slice.h"
33 #include "td/utils/Status.h"
34 #include "td/utils/StringBuilder.h"
35 
36 #include <map>
37 #include <memory>
38 #include <set>
39 #include <unordered_map>
40 #include <unordered_set>
41 #include <utility>
42 
43 namespace td {
44 
45 extern int VERBOSITY_NAME(update_file);
46 
47 class FileData;
48 class FileDbInterface;
49 
50 enum class FileLocationSource : int8 { None, FromUser, FromBinlog, FromDatabase, FromServer };
51 
52 struct NewRemoteFileLocation {
53   NewRemoteFileLocation() = default;
54   NewRemoteFileLocation(RemoteFileLocation remote, FileLocationSource source);
55   RemoteFileLocation partial_or_empty() const;
56   unique_ptr<PartialRemoteFileLocation> partial;
57 
58   //TODO: use RemoteId
59   // hardest part is to determine whether we should flush this location to db.
60   // probably, will need some generation in RemoteInfo
61   optional<FullRemoteFileLocation> full;
62   bool is_full_alive{false};  // if false, then we may try to upload this file
63   FileLocationSource full_source{FileLocationSource::None};
64   int64 ready_size = 0;
65 };
66 
67 class FileNode {
68  public:
FileNode(LocalFileLocation local,NewRemoteFileLocation remote,unique_ptr<FullGenerateFileLocation> generate,int64 size,int64 expected_size,string remote_name,string url,DialogId owner_dialog_id,FileEncryptionKey key,FileId main_file_id,int8 main_file_id_priority)69   FileNode(LocalFileLocation local, NewRemoteFileLocation remote, unique_ptr<FullGenerateFileLocation> generate,
70            int64 size, int64 expected_size, string remote_name, string url, DialogId owner_dialog_id,
71            FileEncryptionKey key, FileId main_file_id, int8 main_file_id_priority)
72       : local_(std::move(local))
73       , remote_(std::move(remote))
74       , generate_(std::move(generate))
75       , size_(size)
76       , expected_size_(expected_size)
77       , remote_name_(std::move(remote_name))
78       , url_(std::move(url))
79       , owner_dialog_id_(owner_dialog_id)
80       , encryption_key_(std::move(key))
81       , main_file_id_(main_file_id)
82       , main_file_id_priority_(main_file_id_priority) {
83     init_ready_size();
84   }
85   void drop_local_location();
86   void set_local_location(const LocalFileLocation &local, int64 ready_size, int64 prefix_offset,
87                           int64 ready_prefix_size);
88   void set_new_remote_location(NewRemoteFileLocation remote);
89   void delete_partial_remote_location();
90   void set_partial_remote_location(PartialRemoteFileLocation remote, int64 ready_size);
91 
92   bool delete_file_reference(Slice file_reference);
93   void set_generate_location(unique_ptr<FullGenerateFileLocation> &&generate);
94   void set_size(int64 size);
95   void set_expected_size(int64 expected_size);
96   void set_remote_name(string remote_name);
97   void set_url(string url);
98   void set_owner_dialog_id(DialogId owner_id);
99   void set_encryption_key(FileEncryptionKey key);
100   void set_upload_pause(FileId upload_pause);
101 
102   void set_download_priority(int8 priority);
103   void set_upload_priority(int8 priority);
104   void set_generate_priority(int8 download_priority, int8 upload_priority);
105 
106   void set_download_offset(int64 download_offset);
107   void set_download_limit(int64 download_limit);
108 
109   void on_changed();
110   void on_info_changed();
111   void on_pmc_changed();
112 
113   bool need_info_flush() const;
114   bool need_pmc_flush() const;
115 
116   void on_pmc_flushed();
117   void on_info_flushed();
118 
119   string suggested_path() const;
120 
121  private:
122   friend class FileView;
123   friend class FileManager;
124 
125   static constexpr char PERSISTENT_ID_VERSION_OLD = 2;
126   static constexpr char PERSISTENT_ID_VERSION_MAP = 3;
127   static constexpr char PERSISTENT_ID_VERSION = 4;
128 
129   LocalFileLocation local_;
130   FileLoadManager::QueryId upload_id_ = 0;
131   int64 download_offset_ = 0;
132   int64 download_limit_ = 0;
133   int64 local_ready_size_ = 0;         // PartialLocal only
134   int64 local_ready_prefix_size_ = 0;  // PartialLocal only
135 
136   NewRemoteFileLocation remote_;
137 
138   FileLoadManager::QueryId download_id_ = 0;
139 
140   unique_ptr<FullGenerateFileLocation> generate_;
141   FileLoadManager::QueryId generate_id_ = 0;
142 
143   int64 size_ = 0;
144   int64 expected_size_ = 0;
145   string remote_name_;
146   string url_;
147   DialogId owner_dialog_id_;
148   FileEncryptionKey encryption_key_;
149   FileDbId pmc_id_;
150   std::vector<FileId> file_ids_;
151 
152   FileId main_file_id_;
153 
154   double last_successful_force_reupload_time_ = -1e10;
155 
156   FileId upload_pause_;
157 
158   int8 upload_priority_ = 0;
159   int8 download_priority_ = 0;
160   int8 generate_priority_ = 0;
161 
162   int8 generate_download_priority_ = 0;
163   int8 generate_upload_priority_ = 0;
164 
165   int8 main_file_id_priority_ = 0;
166 
167   bool is_download_offset_dirty_ = false;
168   bool is_download_limit_dirty_ = false;
169 
170   bool get_by_hash_{false};
171   bool can_search_locally_{true};
172   bool need_reload_photo_{false};
173 
174   bool is_download_started_ = false;
175   bool generate_was_update_ = false;
176 
177   bool need_load_from_pmc_ = false;
178 
179   bool pmc_changed_flag_{false};
180   bool info_changed_flag_{false};
181 
182   bool upload_was_update_file_reference_{false};
183   bool download_was_update_file_reference_{false};
184 
185   bool upload_prefer_small_{false};
186 
187   void init_ready_size();
188 
189   void recalc_ready_prefix_size(int64 prefix_offset, int64 ready_prefix_size);
190 };
191 
192 class FileManager;
193 
194 class FileNodePtr {
195  public:
196   FileNodePtr() = default;
FileNodePtr(FileId file_id,FileManager * file_manager)197   FileNodePtr(FileId file_id, FileManager *file_manager) : file_id_(file_id), file_manager_(file_manager) {
198   }
199 
200   FileNode *operator->() const;
201   FileNode &operator*() const;
202   FileNode *get() const;
203   FullRemoteFileLocation *get_remote() const;
204   explicit operator bool() const;
205 
206  private:
207   FileId file_id_;
208   FileManager *file_manager_ = nullptr;
209   FileNode *get_unsafe() const;
210 };
211 
212 class ConstFileNodePtr {
213  public:
214   ConstFileNodePtr() = default;
ConstFileNodePtr(FileNodePtr file_node_ptr)215   ConstFileNodePtr(FileNodePtr file_node_ptr) : file_node_ptr_(file_node_ptr) {
216   }
217 
218   const FileNode *operator->() const {
219     return file_node_ptr_.operator->();
220   }
221   const FileNode &operator*() const {
222     return file_node_ptr_.operator*();
223   }
224 
225   explicit operator bool() const {
226     return static_cast<bool>(file_node_ptr_);
227   }
get_remote()228   const FullRemoteFileLocation *get_remote() const {
229     return file_node_ptr_.get_remote();
230   }
231 
232  private:
233   FileNodePtr file_node_ptr_;
234 };
235 
236 class FileView {
237  public:
238   FileView() = default;
239   explicit FileView(ConstFileNodePtr node);
240 
241   bool empty() const;
242 
243   bool has_local_location() const;
244   const FullLocalFileLocation &local_location() const;
245   bool has_remote_location() const;
246   bool has_alive_remote_location() const;
247   bool has_active_upload_remote_location() const;
248   bool has_active_download_remote_location() const;
249   const FullRemoteFileLocation &remote_location() const;
250   const FullRemoteFileLocation &main_remote_location() const;
251   bool has_generate_location() const;
252   const FullGenerateFileLocation &generate_location() const;
253 
254   bool has_url() const;
255   const string &url() const;
256 
257   const string &remote_name() const;
258 
259   string suggested_path() const;
260 
261   DialogId owner_dialog_id() const;
262 
263   bool get_by_hash() const;
264 
file_id()265   FileId file_id() const {
266     return node_->main_file_id_;
267   }
268 
269   int64 size() const;
270   int64 expected_size(bool may_guess = false) const;
271   bool is_downloading() const;
272   int64 download_offset() const;
273   int64 downloaded_prefix(int64 offset) const;
274   int64 local_prefix_size() const;
275   int64 local_total_size() const;
276   bool is_uploading() const;
277   int64 remote_size() const;
278   string path() const;
279 
280   int64 get_allocated_local_size() const;
281 
282   bool can_download_from_server() const;
283   bool can_generate() const;
284   bool can_delete() const;
285 
get_type()286   FileType get_type() const {
287     if (has_local_location()) {
288       return local_location().file_type_;
289     }
290     if (has_remote_location()) {
291       return remote_location().file_type_;
292     }
293     if (has_generate_location()) {
294       return generate_location().file_type_;
295     }
296     return FileType::Temp;
297   }
is_encrypted_secret()298   bool is_encrypted_secret() const {
299     return get_type() == FileType::Encrypted;
300   }
is_encrypted_secure()301   bool is_encrypted_secure() const {
302     return get_type() == FileType::Secure;
303   }
is_secure()304   bool is_secure() const {
305     return get_type() == FileType::Secure || get_type() == FileType::SecureRaw;
306   }
is_encrypted_any()307   bool is_encrypted_any() const {
308     return is_encrypted_secret() || is_encrypted_secure();
309   }
is_encrypted()310   bool is_encrypted() const {
311     return is_encrypted_secret() || is_secure();
312   }
encryption_key()313   const FileEncryptionKey &encryption_key() const {
314     return node_->encryption_key_;
315   }
316 
may_reload_photo()317   bool may_reload_photo() const {
318     if (!has_remote_location()) {
319       return false;
320     }
321     if (!remote_location().is_photo()) {
322       return false;
323     }
324     auto type = remote_location().get_source().get_type("may_reload_photo");
325     return type != PhotoSizeSource::Type::Legacy && type != PhotoSizeSource::Type::FullLegacy &&
326            type != PhotoSizeSource::Type::Thumbnail;
327   }
328 
329   string get_persistent_file_id() const;
330 
331   string get_unique_file_id() const;
332 
333  private:
334   ConstFileNodePtr node_{};
335 
336   static string get_unique_id(const FullGenerateFileLocation &location);
337   static string get_unique_id(const FullRemoteFileLocation &location);
338 
339   static string get_persistent_id(const FullGenerateFileLocation &location);
340   static string get_persistent_id(const FullRemoteFileLocation &location);
341 };
342 
343 class FileManager final : public FileLoadManager::Callback {
344  public:
345   class DownloadCallback {
346    public:
347     DownloadCallback() = default;
348     DownloadCallback(const DownloadCallback &) = delete;
349     DownloadCallback &operator=(const DownloadCallback &) = delete;
350     virtual ~DownloadCallback() = default;
on_progress(FileId file_id)351     virtual void on_progress(FileId file_id) {
352     }
353 
354     virtual void on_download_ok(FileId file_id) = 0;
355     virtual void on_download_error(FileId file_id, Status error) = 0;
356   };
357 
358   class UploadCallback {
359    public:
360     UploadCallback() = default;
361     UploadCallback(const UploadCallback &) = delete;
362     UploadCallback &operator=(const UploadCallback &) = delete;
363     virtual ~UploadCallback() = default;
364 
on_progress(FileId file_id)365     virtual void on_progress(FileId file_id) {
366     }
367 
368     // After on_upload_ok all uploads of this file will be paused till merge, delete_partial_remote_location or
369     // explicit upload request with the same file_id.
370     // Also upload may be resumed after some other merges.
371     virtual void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) = 0;
372     virtual void on_upload_encrypted_ok(FileId file_id, tl_object_ptr<telegram_api::InputEncryptedFile> input_file) = 0;
373     virtual void on_upload_secure_ok(FileId file_id, tl_object_ptr<telegram_api::InputSecureFile> input_file) = 0;
374     virtual void on_upload_error(FileId file_id, Status error) = 0;
375   };
376 
377   class Context {
378    public:
379     virtual void on_new_file(int64 size, int64 real_size, int32 cnt) = 0;
380 
381     virtual void on_file_updated(FileId size) = 0;
382 
383     virtual bool add_file_source(FileId file_id, FileSourceId file_source_id) = 0;
384 
385     virtual bool remove_file_source(FileId file_id, FileSourceId file_source_id) = 0;
386 
387     virtual void on_merge_files(FileId to_file_id, FileId from_file_id) = 0;
388 
389     virtual vector<FileSourceId> get_some_file_sources(FileId file_id) = 0;
390 
391     virtual void repair_file_reference(FileId file_id, Promise<Unit> promise) = 0;
392 
393     virtual void reload_photo(PhotoSizeSource source, Promise<Unit> promise) = 0;
394 
395     virtual ActorShared<> create_reference() = 0;
396 
397     Context() = default;
398     Context(const Context &) = delete;
399     Context &operator=(const Context &) = delete;
400     virtual ~Context() = default;
401   };
402 
403   explicit FileManager(unique_ptr<Context> context);
404   FileManager(const FileManager &other) = delete;
405   FileManager &operator=(const FileManager &other) = delete;
406   FileManager(FileManager &&other) = delete;
407   FileManager &operator=(FileManager &&other) = delete;
408   ~FileManager() final;
409 
410   static bool are_modification_times_equal(int64 old_mtime, int64 new_mtime);
411 
412   void init_actor();
413 
414   FileId dup_file_id(FileId file_id);
415 
416   void on_file_unlink(const FullLocalFileLocation &location);
417 
418   FileId register_empty(FileType type);
419   Result<FileId> register_local(FullLocalFileLocation location, DialogId owner_dialog_id, int64 size,
420                                 bool get_by_hash = false, bool force = false,
421                                 bool skip_file_size_checks = false) TD_WARN_UNUSED_RESULT;
422   FileId register_remote(FullRemoteFileLocation location, FileLocationSource file_location_source,
423                          DialogId owner_dialog_id, int64 size, int64 expected_size,
424                          string remote_name) TD_WARN_UNUSED_RESULT;
425   Result<FileId> register_generate(FileType file_type, FileLocationSource file_location_source, string original_path,
426                                    string conversion, DialogId owner_dialog_id,
427                                    int64 expected_size) TD_WARN_UNUSED_RESULT;
428 
429   Result<FileId> merge(FileId x_file_id, FileId y_file_id, bool no_sync = false) TD_WARN_UNUSED_RESULT;
430 
431   void add_file_source(FileId file_id, FileSourceId file_source_id);
432 
433   void remove_file_source(FileId file_id, FileSourceId file_source_id);
434 
435   void change_files_source(FileSourceId file_source_id, const vector<FileId> &old_file_ids,
436                            const vector<FileId> &new_file_ids);
437 
438   void on_file_reference_repaired(FileId file_id, FileSourceId file_source_id, Result<Unit> &&result,
439                                   Promise<Unit> &&promise);
440 
441   bool set_encryption_key(FileId file_id, FileEncryptionKey key);
442   bool set_content(FileId file_id, BufferSlice bytes);
443 
444   void download(FileId file_id, std::shared_ptr<DownloadCallback> callback, int32 new_priority, int64 offset,
445                 int64 limit);
446   void upload(FileId file_id, std::shared_ptr<UploadCallback> callback, int32 new_priority, uint64 upload_order);
447   void resume_upload(FileId file_id, std::vector<int> bad_parts, std::shared_ptr<UploadCallback> callback,
448                      int32 new_priority, uint64 upload_order, bool force = false, bool prefer_small = false);
449   void cancel_upload(FileId file_id);
450   bool delete_partial_remote_location(FileId file_id);
451   void delete_file_reference(FileId file_id, Slice file_reference);
452   void get_content(FileId file_id, Promise<BufferSlice> promise);
453 
454   Result<string> get_suggested_file_name(FileId file_id, const string &directory);
455 
456   void read_file_part(FileId file_id, int32 offset, int32 count, int left_tries,
457                       Promise<td_api::object_ptr<td_api::filePart>> promise);
458 
459   void delete_file(FileId file_id, Promise<Unit> promise, const char *source);
460 
461   void external_file_generate_write_part(int64 id, int32 offset, string data, Promise<> promise);
462   void external_file_generate_progress(int64 id, int32 expected_size, int32 local_prefix_size, Promise<> promise);
463   void external_file_generate_finish(int64 id, Status status, Promise<> promise);
464 
465   Result<FileId> from_persistent_id(CSlice persistent_id, FileType file_type) TD_WARN_UNUSED_RESULT;
466   FileView get_file_view(FileId file_id) const;
467   FileView get_sync_file_view(FileId file_id);
468   td_api::object_ptr<td_api::file> get_file_object(FileId file_id, bool with_main_file_id = true);
469   vector<int32> get_file_ids_object(const vector<FileId> &file_ids, bool with_main_file_id = true);
470 
471   Result<FileId> get_input_thumbnail_file_id(const tl_object_ptr<td_api::InputFile> &thumbnail_input_file,
472                                              DialogId owner_dialog_id, bool is_encrypted) TD_WARN_UNUSED_RESULT;
473   Result<FileId> get_input_file_id(FileType type, const tl_object_ptr<td_api::InputFile> &file,
474                                    DialogId owner_dialog_id, bool allow_zero, bool is_encrypted,
475                                    bool get_by_hash = false, bool is_secure = false) TD_WARN_UNUSED_RESULT;
476 
477   Result<FileId> get_map_thumbnail_file_id(Location location, int32 zoom, int32 width, int32 height, int32 scale,
478                                            DialogId owner_dialog_id) TD_WARN_UNUSED_RESULT;
479 
480   FileType guess_file_type(const tl_object_ptr<td_api::InputFile> &file);
481 
482   vector<tl_object_ptr<telegram_api::InputDocument>> get_input_documents(const vector<FileId> &file_ids);
483 
484   static bool extract_was_uploaded(const tl_object_ptr<telegram_api::InputMedia> &input_media);
485   static bool extract_was_thumbnail_uploaded(const tl_object_ptr<telegram_api::InputMedia> &input_media);
486   static string extract_file_reference(const tl_object_ptr<telegram_api::InputMedia> &input_media);
487 
488   static string extract_file_reference(const tl_object_ptr<telegram_api::InputDocument> &input_document);
489 
490   static string extract_file_reference(const tl_object_ptr<telegram_api::InputPhoto> &input_photo);
491 
492   static bool extract_was_uploaded(const tl_object_ptr<telegram_api::InputChatPhoto> &input_chat_photo);
493   static string extract_file_reference(const tl_object_ptr<telegram_api::InputChatPhoto> &input_chat_photo);
494 
495   template <class StorerT>
496   void store_file(FileId file_id, StorerT &storer, int32 ttl = 5) const;
497 
498   template <class ParserT>
499   FileId parse_file(ParserT &parser);
500 
501  private:
502   Result<FileId> check_input_file_id(FileType type, Result<FileId> result, bool is_encrypted, bool allow_zero,
503                                      bool is_secure) TD_WARN_UNUSED_RESULT;
504 
505   FileId register_url(string url, FileType file_type, FileLocationSource file_location_source,
506                       DialogId owner_dialog_id);
507   Result<FileId> register_file(FileData &&data, FileLocationSource file_location_source, const char *source, bool force,
508                                bool skip_file_size_checks = false);
509 
510   static constexpr int8 FROM_BYTES_PRIORITY = 10;
511 
512   using FileNodeId = int32;
513 
514   using QueryId = FileLoadManager::QueryId;
515   class Query {
516    public:
517     FileId file_id_;
518     enum class Type : int32 {
519       UploadByHash,
520       UploadWaitFileReference,
521       Upload,
522       DownloadWaitFileReference,
523       DownloadReloadDialog,
524       Download,
525       SetContent,
526       Generate
527     } type_;
528   };
529 
530   friend StringBuilder &operator<<(StringBuilder &string_builder, Query::Type type);
531 
532   struct FileIdInfo {
533     FileNodeId node_id_{0};
534     bool send_updates_flag_{false};
535     bool pin_flag_{false};
536     bool sent_file_id_flag_{false};
537 
538     int8 download_priority_{0};
539     int8 upload_priority_{0};
540 
541     uint64 upload_order_{0};
542 
543     std::shared_ptr<DownloadCallback> download_callback_;
544     std::shared_ptr<UploadCallback> upload_callback_;
545   };
546 
547   class ForceUploadActor;
548 
549   ActorShared<> parent_;
550   unique_ptr<Context> context_;
551   std::shared_ptr<FileDbInterface> file_db_;
552 
553   FileIdInfo *get_file_id_info(FileId file_id);
554 
555   struct RemoteInfo {
556     // mutable is set to to enable changing of access hash
557     mutable FullRemoteFileLocation remote_;
558     mutable FileLocationSource file_location_source_;
559     FileId file_id_;
560     bool operator==(const RemoteInfo &other) const {
561       return remote_ == other.remote_;
562     }
563     bool operator<(const RemoteInfo &other) const {
564       return remote_ < other.remote_;
565     }
566   };
567   Enumerator<RemoteInfo> remote_location_info_;
568 
569   std::unordered_map<string, FileId> file_hash_to_file_id_;
570 
571   std::map<FullLocalFileLocation, FileId> local_location_to_file_id_;
572   std::map<FullGenerateFileLocation, FileId> generate_location_to_file_id_;
573   std::map<FileDbId, int32> pmc_id_to_file_node_id_;
574 
575   vector<FileIdInfo> file_id_info_;
576   vector<int32> empty_file_ids_;
577   vector<unique_ptr<FileNode>> file_nodes_;
578   ActorOwn<FileLoadManager> file_load_manager_;
579   ActorOwn<FileGenerateManager> file_generate_manager_;
580 
581   Container<Query> queries_container_;
582 
583   bool is_closed_ = false;
584 
585   std::set<std::string> bad_paths_;
586 
587   FileId next_file_id();
588   FileNodeId next_file_node_id();
589   int32 next_pmc_file_id();
590   FileId create_file_id(int32 file_node_id, FileNode *file_node);
591   void try_forget_file_id(FileId file_id);
592 
593   void load_from_pmc(FileId file_id, FullLocalFileLocation full_local);
594   void load_from_pmc(FileId file_id, const FullRemoteFileLocation &full_remote);
595   void load_from_pmc(FileId file_id, const FullGenerateFileLocation &full_generate);
596   template <class LocationT>
597   void load_from_pmc_impl(FileId file_id, const LocationT &location);
598   void load_from_pmc_result(FileId file_id, Result<FileData> &&result);
599   FileId register_pmc_file_data(FileData &&data);
600 
601   Status check_local_location(FileNodePtr node);
602   static bool try_fix_partial_local_location(FileNodePtr node);
603   Status check_local_location(FullLocalFileLocation &location, int64 &size, bool skip_file_size_checks);
604   void try_flush_node_full(FileNodePtr node, bool new_remote, bool new_local, bool new_generate, FileDbId other_pmc_id);
605   void try_flush_node(FileNodePtr node, const char *source);
606   void try_flush_node_info(FileNodePtr node, const char *source);
607   void try_flush_node_pmc(FileNodePtr node, const char *source);
608   void clear_from_pmc(FileNodePtr node);
609   void flush_to_pmc(FileNodePtr node, bool new_remote, bool new_local, bool new_generate, const char *source);
610   void load_from_pmc(FileNodePtr node, bool new_remote, bool new_local, bool new_generate);
611 
612   Result<FileId> from_persistent_id_map(Slice binary, FileType file_type);
613   Result<FileId> from_persistent_id_v2(Slice binary, FileType file_type);
614   Result<FileId> from_persistent_id_v3(Slice binary, FileType file_type);
615   Result<FileId> from_persistent_id_v23(Slice binary, FileType file_type, int32 version);
616 
617   static string fix_file_extension(Slice file_name, Slice file_type, Slice file_extension);
618   string get_file_name(FileType file_type, Slice path);
619 
get_file_node(FileId file_id)620   ConstFileNodePtr get_file_node(FileId file_id) const {
621     return ConstFileNodePtr{FileNodePtr{file_id, const_cast<FileManager *>(this)}};
622   }
get_file_node(FileId file_id)623   FileNodePtr get_file_node(FileId file_id) {
624     return FileNodePtr{file_id, this};
625   }
626   FileNode *get_file_node_raw(FileId file_id, FileNodeId *file_node_id = nullptr);
627 
628   FileNodePtr get_sync_file_node(FileId file_id);
629 
630   void on_force_reupload_success(FileId file_id);
631 
632   // void release_file_node(FileNodeId id);
633   void do_cancel_download(FileNodePtr node);
634   void do_cancel_upload(FileNodePtr node);
635   void do_cancel_generate(FileNodePtr node);
636   void run_upload(FileNodePtr node, std::vector<int> bad_parts);
637   void run_download(FileNodePtr node, bool force_update_priority);
638   void run_generate(FileNodePtr node);
639 
640   void on_start_download(QueryId query_id) final;
641   void on_partial_download(QueryId query_id, PartialLocalFileLocation partial_local, int64 ready_size,
642                            int64 size) final;
643   void on_hash(QueryId query_id, string hash) final;
644   void on_partial_upload(QueryId query_id, PartialRemoteFileLocation partial_remote, int64 ready_size) final;
645   void on_download_ok(QueryId query_id, FullLocalFileLocation local, int64 size, bool is_new) final;
646   void on_upload_ok(QueryId query_id, FileType file_type, PartialRemoteFileLocation partial_remote, int64 size) final;
647   void on_upload_full_ok(QueryId query_id, FullRemoteFileLocation remote) final;
648   void on_error(QueryId query_id, Status status) final;
649 
650   void on_error_impl(FileNodePtr node, Query::Type type, bool was_active, Status status);
651 
652   void on_partial_generate(QueryId, PartialLocalFileLocation partial_local, int32 expected_size);
653   void on_generate_ok(QueryId, FullLocalFileLocation local);
654 
655   std::pair<Query, bool> finish_query(QueryId query_id);
656 
657   FullRemoteFileLocation *get_remote(int32 key);
658 
659   std::unordered_set<FileId, FileIdHash> get_main_file_ids(const vector<FileId> &file_ids);
660 
661   void hangup() final;
662   void tear_down() final;
663 
664   friend class FileNodePtr;
665 };
666 
667 }  // namespace td
668