Ton

Форк
0
/
dht-bucket.cpp 
231 строка · 6.3 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

4
    TON Blockchain Library is free software: you can redistribute it and/or modify
5
    it under the terms of the GNU Lesser General Public License as published by
6
    the Free Software Foundation, either version 2 of the License, or
7
    (at your option) any later version.
8

9
    TON Blockchain Library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13

14
    You should have received a copy of the GNU Lesser General Public License
15
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
16

17
    Copyright 2017-2020 Telegram Systems LLP
18
*/
19
#include "td/utils/tl_storers.h"
20
#include "td/utils/crypto.h"
21
#include "td/utils/tl_parsers.h"
22
#include "td/utils/Random.h"
23

24
#include "td/utils/format.h"
25

26
#include "keys/encryptor.h"
27

28
#include "auto/tl/ton_api.hpp"
29

30
#include "dht-remote-node.hpp"
31
#include "dht-bucket.hpp"
32
#include "dht.hpp"
33

34
//#include <algorithm>
35

36
namespace ton {
37

38
namespace dht {
39

40
void DhtBucket::get_nearest_nodes(DhtKeyId id, td::uint32 bit, DhtNodesList &vec, td::uint32 k) {
41
  if (active_nodes_.size() == 0) {
42
    return;
43
  }
44
  std::map<DhtKeyId, size_t> list;
45

46
  for (size_t i = 0; i < active_nodes_.size(); i++) {
47
    auto &node = active_nodes_[i];
48
    if (node) {
49
      list.emplace(id ^ node->get_key(), i);
50
    }
51
  }
52

53
  for (auto it = list.begin(); it != list.end() && vec.size() < k; it++) {
54
    vec.push_back(active_nodes_[it->second]->get_node());
55
  }
56
}
57

58
td::uint32 DhtBucket::active_cnt() {
59
  td::uint32 cnt = 0;
60
  for (auto &node : active_nodes_) {
61
    if (node) {
62
      cnt++;
63
    }
64
  }
65
  return cnt;
66
}
67

68
td::Status DhtBucket::add_full_node(DhtKeyId id, DhtNode newnode, td::actor::ActorId<adnl::Adnl> adnl,
69
                                    adnl::AdnlNodeIdShort self_id, td::int32 our_network_id, bool set_active) {
70
  for (auto &node : active_nodes_) {
71
    if (node && node->get_key() == id) {
72
      if (set_active) {
73
        return node->receive_ping(std::move(newnode), adnl, self_id);
74
      } else {
75
        return node->update_value(std::move(newnode), adnl, self_id);
76
      }
77
    }
78
  }
79
  for (size_t i = 0; i < backup_nodes_.size(); ++i) {
80
    auto &node = backup_nodes_[i];
81
    if (node && node->get_key() == id) {
82
      if (set_active) {
83
        TRY_STATUS(node->receive_ping(std::move(newnode), adnl, self_id));
84
        if (node->is_ready()) {
85
          promote_node(i);
86
        }
87
        return td::Status::OK();
88
      } else {
89
        return node->update_value(std::move(newnode), adnl, self_id);
90
      }
91
    }
92
  }
93

94
  TRY_RESULT_PREFIX(N, DhtRemoteNode::create(std::move(newnode), max_missed_pings_, our_network_id),
95
                    "failed to add new node: ");
96
  if (set_active) {
97
    for (auto &node : active_nodes_) {
98
      if (node == nullptr) {
99
        node = std::move(N);
100
        node->receive_ping();
101
        return td::Status::OK();
102
      }
103
    }
104
  }
105

106
  size_t idx = select_backup_node_to_drop();
107
  if (idx < backup_nodes_.size()) {
108
    backup_nodes_[idx] = std::move(N);
109
  }
110
  return td::Status::OK();
111
}
112

113
size_t DhtBucket::select_backup_node_to_drop() const {
114
  size_t result = backup_nodes_.size();
115
  for (size_t idx = 0; idx < backup_nodes_.size(); ++idx) {
116
    const auto &node = backup_nodes_[idx];
117
    if (node == nullptr) {
118
      return idx;
119
    }
120
    if (node->ready_from() == 0 && node->failed_from() + 60 < td::Time::now_cached()) {
121
      if (result == backup_nodes_.size() || node->failed_from() < backup_nodes_[result]->failed_from()) {
122
        result = idx;
123
      }
124
    }
125
  }
126
  return result;
127
}
128

129
void DhtBucket::receive_ping(DhtKeyId id, DhtNode result, td::actor::ActorId<adnl::Adnl> adnl,
130
                             adnl::AdnlNodeIdShort self_id) {
131
  for (auto &node : active_nodes_) {
132
    if (node && node->get_key() == id) {
133
      node->receive_ping(std::move(result), adnl, self_id);
134
      return;
135
    }
136
  }
137
  for (size_t i = 0; i < backup_nodes_.size(); i++) {
138
    auto &node = backup_nodes_[i];
139
    if (node && node->get_key() == id) {
140
      node->receive_ping(std::move(result), adnl, self_id);
141
      if (node->is_ready()) {
142
        promote_node(i);
143
      }
144
      return;
145
    }
146
  }
147
}
148

149
void DhtBucket::demote_node(size_t idx) {
150
  size_t new_idx = select_backup_node_to_drop();
151
  if (new_idx < backup_nodes_.size()) {
152
    backup_nodes_[new_idx] = std::move(active_nodes_[idx]);
153
  }
154
  active_nodes_[idx] = nullptr;
155
}
156

157
void DhtBucket::promote_node(size_t idx) {
158
  CHECK(backup_nodes_[idx]);
159
  for (auto &node : active_nodes_) {
160
    if (node == nullptr) {
161
      node = std::move(backup_nodes_[idx]);
162
      return;
163
    }
164
    CHECK(node->is_ready());
165
  }
166
}
167

168
void DhtBucket::check(bool client_only, td::actor::ActorId<adnl::Adnl> adnl, td::actor::ActorId<DhtMember> dht,
169
                      adnl::AdnlNodeIdShort src) {
170
  size_t have_space = 0;
171
  for (size_t i = 0; i < active_nodes_.size(); i++) {
172
    auto &node = active_nodes_[i];
173
    if (node && td::Time::now_cached() - node->last_ping_at() > node->ping_interval()) {
174
      node->send_ping(client_only, adnl, dht, src);
175
      if (node->ready_from() == 0) {
176
        demote_node(i);
177
      }
178
    }
179
    if (node == nullptr) {
180
      have_space++;
181
    }
182
  }
183
  for (size_t i = 0; i < backup_nodes_.size(); i++) {
184
    auto &node = backup_nodes_[i];
185
    if (node && td::Time::now_cached() - node->last_ping_at() > node->ping_interval()) {
186
      node->send_ping(client_only, adnl, dht, src);
187
    }
188
    if (node && have_space > 0 && node->is_ready()) {
189
      promote_node(i);
190
      have_space--;
191
    }
192
  }
193
}
194

195
void DhtBucket::dump(td::StringBuilder &sb) const {
196
  sb << "  bucket:\n";
197
  sb << "    active:\n";
198
  for (auto &node : active_nodes_) {
199
    if (node) {
200
      sb << "      " << node->get_key() << "\n";
201
    }
202
  }
203
  sb << "    backup:\n";
204
  for (auto &node : backup_nodes_) {
205
    if (node) {
206
      sb << "      " << node->get_key() << "\n";
207
    }
208
  }
209
}
210

211
DhtNodesList DhtBucket::export_nodes() const {
212
  DhtNodesList list;
213
  for (auto &node : active_nodes_) {
214
    if (node) {
215
      list.push_back(node->get_node());
216
    }
217
  }
218
  for (auto &node : backup_nodes_) {
219
    if (node) {
220
      list.push_back(node->get_node());
221
    }
222
  }
223
  if (list.size() > k_) {
224
    list.list().resize(k_);
225
  }
226
  return list;
227
}
228

229
}  // namespace dht
230

231
}  // namespace ton
232

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.