Use array-based MessageIdDuplicateChecker.
This commit is contained in:
parent
b3aa31d398
commit
6507fb7602
@ -533,40 +533,40 @@ class MessageIdDuplicateCheckerNewSimple {
|
|||||||
std::set<td::int64> saved_message_ids_;
|
std::set<td::int64> saved_message_ids_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t MAX_SAVED_MESSAGE_IDS>
|
template <size_t max_size>
|
||||||
class MessageIdDuplicateCheckerArray {
|
class MessageIdDuplicateCheckerArray {
|
||||||
public:
|
public:
|
||||||
static td::string get_description() {
|
static td::string get_description() {
|
||||||
return PSTRING() << "Array" << MAX_SAVED_MESSAGE_IDS;
|
return PSTRING() << "Array" << max_size;
|
||||||
}
|
}
|
||||||
td::Status check(td::int64 message_id) {
|
td::Status check(td::int64 message_id) {
|
||||||
if (end_pos == 2 * MAX_SAVED_MESSAGE_IDS) {
|
if (end_pos_ == 2 * max_size) {
|
||||||
std::copy_n(&saved_message_ids_[MAX_SAVED_MESSAGE_IDS], MAX_SAVED_MESSAGE_IDS, &saved_message_ids_[0]);
|
std::copy_n(&saved_message_ids_[max_size], max_size, &saved_message_ids_[0]);
|
||||||
end_pos = MAX_SAVED_MESSAGE_IDS;
|
end_pos_ = max_size;
|
||||||
}
|
}
|
||||||
if (end_pos == 0 || message_id > saved_message_ids_[end_pos - 1]) {
|
if (end_pos_ == 0 || message_id > saved_message_ids_[end_pos_ - 1]) {
|
||||||
// fast path
|
// fast path
|
||||||
saved_message_ids_[end_pos++] = message_id;
|
saved_message_ids_[end_pos_++] = message_id;
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
}
|
}
|
||||||
if (end_pos >= MAX_SAVED_MESSAGE_IDS && message_id < saved_message_ids_[0]) {
|
if (end_pos_ >= max_size && message_id < saved_message_ids_[0]) {
|
||||||
return td::Status::Error(2, PSLICE() << "Ignore very old message_id "
|
return td::Status::Error(2, PSLICE() << "Ignore very old message_id "
|
||||||
<< td::tag("oldest message_id", saved_message_ids_[0])
|
<< td::tag("oldest message_id", saved_message_ids_[0])
|
||||||
<< td::tag("got message_id", message_id));
|
<< td::tag("got message_id", message_id));
|
||||||
}
|
}
|
||||||
auto it = std::lower_bound(&saved_message_ids_[0], &saved_message_ids_[end_pos], message_id);
|
auto it = std::lower_bound(&saved_message_ids_[0], &saved_message_ids_[end_pos_], message_id);
|
||||||
if (*it == message_id) {
|
if (*it == message_id) {
|
||||||
return td::Status::Error(1, PSLICE() << "Ignore duplicated message_id " << td::tag("message_id", message_id));
|
return td::Status::Error(1, PSLICE() << "Ignore duplicated message_id " << td::tag("message_id", message_id));
|
||||||
}
|
}
|
||||||
std::copy_backward(it, &saved_message_ids_[end_pos], &saved_message_ids_[end_pos + 1]);
|
std::copy_backward(it, &saved_message_ids_[end_pos_], &saved_message_ids_[end_pos_ + 1]);
|
||||||
*it = message_id;
|
*it = message_id;
|
||||||
++end_pos;
|
++end_pos_;
|
||||||
return td::Status::OK();
|
return td::Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<td::int64, 2 * MAX_SAVED_MESSAGE_IDS> saved_message_ids_;
|
std::array<td::int64, 2 * max_size> saved_message_ids_;
|
||||||
std::size_t end_pos = 0;
|
std::size_t end_pos_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -17,25 +17,31 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
namespace mtproto {
|
namespace mtproto {
|
||||||
|
|
||||||
Status MessageIdDuplicateChecker::check(int64 message_id) {
|
Status check_message_id_duplicates(int64 *saved_message_ids, size_t max_size, size_t &end_pos, int64 message_id) {
|
||||||
// In addition, the identifiers (msg_id) of the last N messages received from the other side must be stored, and if
|
// In addition, the identifiers (msg_id) of the last N messages received from the other side must be stored, and if
|
||||||
// a message comes in with msg_id lower than all or equal to any of the stored values, that message is to be
|
// a message comes in with msg_id lower than all or equal to any of the stored values, that message is to be
|
||||||
// ignored. Otherwise, the new message msg_id is added to the set, and, if the number of stored msg_id values is
|
// ignored. Otherwise, the new message msg_id is added to the set, and, if the number of stored msg_id values is
|
||||||
// greater than N, the oldest (i. e. the lowest) is forgotten.
|
// greater than N, the oldest (i. e. the lowest) is forgotten.
|
||||||
auto insert_result = saved_message_ids_.insert(message_id);
|
if (end_pos == 2 * max_size) {
|
||||||
if (!insert_result.second) {
|
std::copy_n(&saved_message_ids[max_size], max_size, &saved_message_ids[0]);
|
||||||
return Status::Error(1, PSLICE() << "Ignore duplicated message_id " << tag("message_id", message_id));
|
end_pos = max_size;
|
||||||
}
|
}
|
||||||
if (saved_message_ids_.size() == MAX_SAVED_MESSAGE_IDS + 1) {
|
if (end_pos == 0 || message_id > saved_message_ids[end_pos - 1]) {
|
||||||
auto begin_it = saved_message_ids_.begin();
|
// fast path
|
||||||
bool is_very_old = begin_it == insert_result.first;
|
saved_message_ids[end_pos++] = message_id;
|
||||||
saved_message_ids_.erase(begin_it);
|
return Status::OK();
|
||||||
if (is_very_old) {
|
}
|
||||||
return Status::Error(2, PSLICE() << "Ignore very old message_id "
|
if (end_pos >= max_size && message_id < saved_message_ids[0]) {
|
||||||
<< tag("oldest message_id", *saved_message_ids_.begin())
|
return Status::Error(2, PSLICE() << "Ignore very old message_id " << tag("oldest message_id", saved_message_ids[0])
|
||||||
<< tag("got message_id", message_id));
|
<< tag("got message_id", message_id));
|
||||||
}
|
}
|
||||||
|
auto it = std::lower_bound(&saved_message_ids[0], &saved_message_ids[end_pos], message_id);
|
||||||
|
if (*it == message_id) {
|
||||||
|
return Status::Error(1, PSLICE() << "Ignore duplicated message_id " << tag("message_id", message_id));
|
||||||
}
|
}
|
||||||
|
std::copy_backward(it, &saved_message_ids[end_pos], &saved_message_ids[end_pos + 1]);
|
||||||
|
*it = message_id;
|
||||||
|
++end_pos;
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "td/utils/Slice.h"
|
#include "td/utils/Slice.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
#include <set>
|
#include <array>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace mtproto {
|
namespace mtproto {
|
||||||
@ -37,13 +37,18 @@ void parse(ServerSalt &salt, ParserT &parser) {
|
|||||||
salt.valid_until = parser.fetch_double();
|
salt.valid_until = parser.fetch_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status check_message_id_duplicates(int64 *saved_message_ids, size_t max_size, size_t &end_pos, int64 message_id);
|
||||||
|
|
||||||
|
template <size_t max_size>
|
||||||
class MessageIdDuplicateChecker {
|
class MessageIdDuplicateChecker {
|
||||||
public:
|
public:
|
||||||
Status check(int64 message_id);
|
Status check(int64 message_id) {
|
||||||
|
return check_message_id_duplicates(&saved_message_ids_[0], max_size, end_pos_, message_id);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t MAX_SAVED_MESSAGE_IDS = 1000;
|
std::array<int64, 2 * max_size> saved_message_ids_;
|
||||||
std::set<int64> saved_message_ids_;
|
size_t end_pos_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AuthData {
|
class AuthData {
|
||||||
@ -274,8 +279,8 @@ class AuthData {
|
|||||||
|
|
||||||
std::vector<ServerSalt> future_salts_;
|
std::vector<ServerSalt> future_salts_;
|
||||||
|
|
||||||
MessageIdDuplicateChecker duplicate_checker_;
|
MessageIdDuplicateChecker<1000> duplicate_checker_;
|
||||||
MessageIdDuplicateChecker updates_duplicate_checker_;
|
MessageIdDuplicateChecker<1000> updates_duplicate_checker_;
|
||||||
|
|
||||||
void update_salt(double now);
|
void update_salt(double now);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user