summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/td/telegram/files/FileLoader.h
blob: c4ede47e1ddcd65163c0150bc81c37ef5bcc5fe1 (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
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2023
//
// 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/DelayDispatcher.h"
#include "td/telegram/files/FileLoaderActor.h"
#include "td/telegram/files/FileLocation.h"
#include "td/telegram/files/PartsManager.h"
#include "td/telegram/files/ResourceManager.h"
#include "td/telegram/files/ResourceState.h"
#include "td/telegram/net/NetQuery.h"

#include "td/actor/actor.h"

#include "td/utils/OrderedEventsProcessor.h"
#include "td/utils/Status.h"

#include <map>
#include <utility>

namespace td {

class FileLoader : public FileLoaderActor {
 public:
  class Callback {
   public:
    Callback() = default;
    Callback(const Callback &) = delete;
    Callback &operator=(const Callback &) = delete;
    virtual ~Callback() = default;
  };
  void set_resource_manager(ActorShared<ResourceManager> resource_manager) final;
  void update_priority(int8 priority) final;
  void update_resources(const ResourceState &other) final;

  void update_local_file_location(const LocalFileLocation &local) final;
  void update_downloaded_part(int64 offset, int64 limit, int64 max_resource_limit) final;

 protected:
  void set_ordered_flag(bool flag);
  size_t get_part_size() const;

  struct PrefixInfo {
    int64 size = -1;
    bool is_ready = false;
  };
  struct FileInfo {
    int64 size{0};
    int64 expected_size{0};
    bool is_size_final{false};
    int32 part_size{0};
    std::vector<int> ready_parts;
    bool use_part_count_limit{true};
    bool only_check{false};
    bool need_delay{false};
    int64 offset{0};
    int64 limit{0};
    bool is_upload{false};
  };
  virtual Result<FileInfo> init() TD_WARN_UNUSED_RESULT = 0;
  virtual Status on_ok(int64 size) TD_WARN_UNUSED_RESULT = 0;
  virtual void on_error(Status status) = 0;
  virtual Status before_start_parts() {
    return Status::OK();
  }
  virtual Result<std::pair<NetQueryPtr, bool>> start_part(Part part, int part_count,
                                                          int64 streaming_offset) TD_WARN_UNUSED_RESULT = 0;
  virtual void after_start_parts() {
  }
  virtual Result<size_t> process_part(Part part, NetQueryPtr net_query) TD_WARN_UNUSED_RESULT = 0;
  struct Progress {
    int32 part_count{0};
    int32 part_size{0};
    int32 ready_part_count{0};
    string ready_bitmask;
    bool is_ready{false};
    int64 ready_size{0};
    int64 size{0};
  };
  virtual void on_progress(Progress progress) = 0;
  virtual Callback *get_callback() = 0;
  virtual Result<PrefixInfo> on_update_local_location(const LocalFileLocation &location,
                                                      int64 file_size) TD_WARN_UNUSED_RESULT {
    return Status::Error("Unsupported");
  }
  virtual Result<bool> should_restart_part(Part part, NetQueryPtr &net_query) TD_WARN_UNUSED_RESULT {
    return false;
  }

  virtual Status process_check_query(NetQueryPtr net_query) {
    return Status::Error("Unsupported");
  }
  struct CheckInfo {
    bool need_check{false};
    bool changed{false};
    int64 checked_prefix_size{0};
    std::vector<NetQueryPtr> queries;
  };
  virtual Result<CheckInfo> check_loop(int64 checked_prefix_size, int64 ready_prefix_size, bool is_ready) {
    return CheckInfo{};
  }

  virtual void keep_fd_flag(bool keep_fd) {
  }

 private:
  static constexpr uint8 COMMON_QUERY_KEY = 2;
  bool stop_flag_ = false;
  ActorShared<ResourceManager> resource_manager_;
  ResourceState resource_state_;
  PartsManager parts_manager_;
  uint64 blocking_id_{0};
  std::map<uint64, std::pair<Part, ActorShared<>>> part_map_;
  bool ordered_flag_ = false;
  OrderedEventsProcessor<std::pair<Part, NetQueryPtr>> ordered_parts_;
  ActorOwn<DelayDispatcher> delay_dispatcher_;
  double next_delay_ = 0;

  uint32 debug_total_parts_ = 0;
  uint32 debug_bad_part_order_ = 0;
  std::vector<int32> debug_bad_parts_;

  void start_up() final;
  void loop() final;
  Status do_loop();
  void hangup() final;
  void hangup_shared() final;
  void tear_down() final;

  void update_estimated_limit();
  void on_progress_impl();

  void on_result(NetQueryPtr query) final;
  void on_part_query(Part part, NetQueryPtr query);
  void on_common_query(NetQueryPtr query);
  Status try_on_part_query(Part part, NetQueryPtr query);
};

}  // namespace td