aboutsummaryrefslogtreecommitdiffhomepage
path: root/td/telegram/files/FileLoadManager.h
blob: 95884eca715a57984bb5e511c3b4cc52d2f69591 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once

#include "td/telegram/files/FileDownloader.h"
#include "td/telegram/files/FileEncryptionKey.h"
#include "td/telegram/files/FileFromBytes.h"
#include "td/telegram/files/FileHashUploader.h"
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/FileType.h"
#include "td/telegram/files/FileUploader.h"
#include "td/telegram/files/ResourceManager.h"
#include "td/telegram/net/DcId.h"

#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"

#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Container.h"
#include "td/utils/Status.h"

#include <map>

namespace td {

class FileLoadManager final : public Actor {
 public:
  using QueryId = uint64;
  class Callback : public Actor {
   public:
    virtual void on_start_download(QueryId id) = 0;
    virtual void on_partial_download(QueryId id, PartialLocalFileLocation partial_local, int64 ready_size,
                                     int64 size) = 0;
    virtual void on_partial_upload(QueryId id, PartialRemoteFileLocation partial_remote, int64 ready_size) = 0;
    virtual void on_hash(QueryId id, string hash) = 0;
    virtual void on_upload_ok(QueryId id, FileType file_type, PartialRemoteFileLocation remtoe, int64 size) = 0;
    virtual void on_upload_full_ok(QueryId id, FullRemoteFileLocation remote) = 0;
    virtual void on_download_ok(QueryId id, FullLocalFileLocation local, int64 size, bool is_new) = 0;
    virtual void on_error(QueryId id, Status status) = 0;
  };

  explicit FileLoadManager(ActorShared<Callback> callback, ActorShared<> parent);

  void download(QueryId id, const FullRemoteFileLocation &remote_location, const LocalFileLocation &local, int64 size,
                string name, const FileEncryptionKey &encryption_key, bool search_file, int64 offset, int64 limit,
                int8 priority);
  void upload(QueryId id, const LocalFileLocation &local_location, const RemoteFileLocation &remote_location,
              int64 expected_size, const FileEncryptionKey &encryption_key, int8 priority, vector<int> bad_parts);
  void upload_by_hash(QueryId id, const FullLocalFileLocation &local_location, int64 size, int8 priority);
  void update_priority(QueryId id, int8 priority);
  void from_bytes(QueryId id, FileType type, BufferSlice bytes, string name);
  void cancel(QueryId id);
  void update_local_file_location(QueryId id, const LocalFileLocation &local);
  void update_downloaded_part(QueryId id, int64 offset, int64 limit);

  void get_content(string file_path, Promise<BufferSlice> promise);

  void read_file_part(string file_path, int64 offset, int64 count, Promise<string> promise);

  void unlink_file(string file_path, Promise<Unit> promise);

 private:
  struct Node {
    QueryId query_id_;
    ActorOwn<FileLoaderActor> loader_;
    ResourceState resource_state_;
  };
  using NodeId = uint64;

  std::map<DcId, ActorOwn<ResourceManager>> download_resource_manager_map_;
  std::map<DcId, ActorOwn<ResourceManager>> download_small_resource_manager_map_;
  ActorOwn<ResourceManager> upload_resource_manager_;

  Container<Node> nodes_container_;
  ActorShared<Callback> callback_;
  ActorShared<> parent_;
  std::map<QueryId, NodeId> query_id_to_node_id_;
  int64 max_resource_limit_ = 1 << 21;
  bool stop_flag_ = false;

  void start_up() final;
  void loop() final;
  void hangup() final;
  void hangup_shared() final;

  void close_node(NodeId node_id);
  ActorOwn<ResourceManager> &get_download_resource_manager(bool is_small, DcId dc_id);

  void on_start_download();
  void on_partial_download(PartialLocalFileLocation partial_local, int64 ready_size, int64 size);
  void on_partial_upload(PartialRemoteFileLocation partial_remote, int64 ready_size);
  void on_hash(string hash);
  void on_ok_download(FullLocalFileLocation local, int64 size, bool is_new);
  void on_ok_upload(FileType file_type, PartialRemoteFileLocation remote, int64 size);
  void on_ok_upload_full(FullRemoteFileLocation remote);
  void on_error(Status status);
  void on_error_impl(NodeId node_id, Status status);

  class FileDownloaderCallback final : public FileDownloader::Callback {
   public:
    explicit FileDownloaderCallback(ActorShared<FileLoadManager> actor_id) : actor_id_(std::move(actor_id)) {
    }

   private:
    ActorShared<FileLoadManager> actor_id_;

    void on_start_download() final {
      send_closure(actor_id_, &FileLoadManager::on_start_download);
    }
    void on_partial_download(PartialLocalFileLocation partial_local, int64 ready_size, int64 size) final {
      send_closure(actor_id_, &FileLoadManager::on_partial_download, std::move(partial_local), ready_size, size);
    }
    void on_ok(FullLocalFileLocation full_local, int64 size, bool is_new) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_ok_download, std::move(full_local), size, is_new);
    }
    void on_error(Status status) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_error, std::move(status));
    }
  };

  class FileUploaderCallback final : public FileUploader::Callback {
   public:
    explicit FileUploaderCallback(ActorShared<FileLoadManager> actor_id) : actor_id_(std::move(actor_id)) {
    }

   private:
    ActorShared<FileLoadManager> actor_id_;

    void on_hash(string hash) final {
      send_closure(actor_id_, &FileLoadManager::on_hash, std::move(hash));
    }
    void on_partial_upload(PartialRemoteFileLocation partial_remote, int64 ready_size) final {
      send_closure(actor_id_, &FileLoadManager::on_partial_upload, std::move(partial_remote), ready_size);
    }
    void on_ok(FileType file_type, PartialRemoteFileLocation partial_remote, int64 size) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_ok_upload, file_type, std::move(partial_remote), size);
    }
    void on_error(Status status) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_error, std::move(status));
    }
  };
  class FileHashUploaderCallback final : public FileHashUploader::Callback {
   public:
    explicit FileHashUploaderCallback(ActorShared<FileLoadManager> actor_id) : actor_id_(std::move(actor_id)) {
    }

   private:
    ActorShared<FileLoadManager> actor_id_;

    void on_ok(FullRemoteFileLocation remote) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_ok_upload_full, std::move(remote));
    }
    void on_error(Status status) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_error, std::move(status));
    }
  };

  class FileFromBytesCallback final : public FileFromBytes::Callback {
   public:
    explicit FileFromBytesCallback(ActorShared<FileLoadManager> actor_id) : actor_id_(std::move(actor_id)) {
    }

   private:
    ActorShared<FileLoadManager> actor_id_;

    void on_ok(const FullLocalFileLocation &full_local, int64 size) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_ok_download, full_local, size, true);
    }
    void on_error(Status status) final {
      send_closure(std::move(actor_id_), &FileLoadManager::on_error, std::move(status));
    }
  };
};

}  // namespace td