diff --git a/td/generate/tl_json_converter.cpp b/td/generate/tl_json_converter.cpp index 8f4ee721c..673306aed 100644 --- a/td/generate/tl_json_converter.cpp +++ b/td/generate/tl_json_converter.cpp @@ -136,7 +136,7 @@ void gen_tl_constructor_from_string(StringBuilder &sb, Slice name, const Vec &ve return; } sb << " {\n"; - sb << " static const std::unordered_map m = {\n"; + sb << " static const FlatHashMap m = {\n"; bool is_first = true; for (auto &p : vec) { @@ -216,10 +216,10 @@ void gen_json_converter_file(const tl::simple::Schema &schema, const std::string sb << "#include \"td/utils/base64.h\"\n"; sb << "#include \"td/utils/common.h\"\n"; + sb << "#include \"td/utils/FlatHashMap.h\"\n"; sb << "#include \"td/utils/Slice.h\"\n\n"; - sb << "#include \n"; - sb << "#include \n\n"; + sb << "#include \n\n"; } sb << "namespace td {\n"; sb << "namespace td_api {\n"; diff --git a/td/mtproto/RawConnection.cpp b/td/mtproto/RawConnection.cpp index 00c1e1f8d..a663e6af3 100644 --- a/td/mtproto/RawConnection.cpp +++ b/td/mtproto/RawConnection.cpp @@ -15,6 +15,7 @@ #include "td/net/DarwinHttp.h" #endif +#include "td/utils/FlatHashMap.h" #include "td/utils/format.h" #include "td/utils/logging.h" #include "td/utils/misc.h" @@ -26,7 +27,6 @@ #include "td/utils/StorerBase.h" #include -#include #include namespace td { @@ -67,6 +67,7 @@ class RawConnectionDefault final : public RawConnection { bool use_quick_ack = false; if (quick_ack_token != 0 && transport_->support_quick_ack()) { + CHECK(info.message_ack & (1u << 31)); auto tmp = quick_ack_to_token_.emplace(info.message_ack, quick_ack_token); if (tmp.second) { use_quick_ack = true; @@ -130,7 +131,7 @@ class RawConnectionDefault final : public RawConnection { PublicFields extra_; BufferedFd socket_fd_; unique_ptr transport_; - std::unordered_map quick_ack_to_token_; + FlatHashMap quick_ack_to_token_; bool has_error_{false}; unique_ptr stats_callback_; @@ -218,11 +219,15 @@ class RawConnectionDefault final : public RawConnection { } Status on_quick_ack(uint32 quick_ack, Callback &callback) { + if ((quick_ack & (1u << 31)) == 0) { + LOG(ERROR) << "Receive invalid quick_ack " << quick_ack; + return Status::OK(); + } + auto it = quick_ack_to_token_.find(quick_ack); if (it == quick_ack_to_token_.end()) { - LOG(WARNING) << Status::Error(PSLICE() << "Unknown quick_ack " << quick_ack); + LOG(WARNING) << "Receive unknown quick_ack " << quick_ack; return Status::OK(); - // TODO: return Status::Error(PSLICE() << "Unknown quick_ack " << quick_ack); } auto token = it->second; quick_ack_to_token_.erase(it); diff --git a/td/mtproto/SessionConnection.cpp b/td/mtproto/SessionConnection.cpp index 58380aa64..05f3dfa0c 100644 --- a/td/mtproto/SessionConnection.cpp +++ b/td/mtproto/SessionConnection.cpp @@ -437,13 +437,13 @@ Status SessionConnection::on_packet(const MsgInfo &info, const mtproto_api::msgs if (it == service_queries_.end()) { return Status::Error("Unknown msgs_state_info"); } - SCOPE_EXIT { - service_queries_.erase(it); - }; - if (it->second.type != ServiceQuery::GetStateInfo) { - return Status::Error("Got msg_state_info in response not to GetStateInfo"); + auto query = std::move(it->second); + service_queries_.erase(it); + + if (query.type != ServiceQuery::GetStateInfo) { + return Status::Error("Receive msg_state_info in response not to GetStateInfo"); } - return on_msgs_state_info(it->second.message_ids, msgs_state_info.info_); + return on_msgs_state_info(query.message_ids, msgs_state_info.info_); } Status SessionConnection::on_packet(const MsgInfo &info, const mtproto_api::msgs_all_info &msgs_all_info) { @@ -573,8 +573,9 @@ void SessionConnection::on_message_failed(uint64 id, Status status) { auto cit = container_to_service_msg_.find(id); if (cit != container_to_service_msg_.end()) { - for (auto nid : cit->second) { - on_message_failed_inner(nid); + auto message_ids = cit->second; + for (auto message_id : message_ids) { + on_message_failed_inner(message_id); } } else { on_message_failed_inner(id); @@ -586,21 +587,25 @@ void SessionConnection::on_message_failed_inner(uint64 id) { if (it == service_queries_.end()) { return; } - switch (it->second.type) { + auto query = std::move(it->second); + service_queries_.erase(it); + + switch (query.type) { case ServiceQuery::ResendAnswer: { - for (auto message_id : it->second.message_ids) { + for (auto message_id : query.message_ids) { resend_answer(message_id); } break; } case ServiceQuery::GetStateInfo: { - for (auto message_id : it->second.message_ids) { + for (auto message_id : query.message_ids) { get_state_info(message_id); } break; } + default: + UNREACHABLE(); } - service_queries_.erase(id); } bool SessionConnection::must_flush_packet() { @@ -968,11 +973,10 @@ void SessionConnection::flush_packet() { } if (resend_answer_id) { - service_queries_.insert({resend_answer_id, ServiceQuery{ServiceQuery::ResendAnswer, std::move(to_resend_answer)}}); + service_queries_.emplace(resend_answer_id, ServiceQuery{ServiceQuery::ResendAnswer, std::move(to_resend_answer)}); } if (get_state_info_id) { - service_queries_.insert( - {get_state_info_id, ServiceQuery{ServiceQuery::GetStateInfo, std::move(to_get_state_info)}}); + service_queries_.emplace(get_state_info_id, ServiceQuery{ServiceQuery::GetStateInfo, std::move(to_get_state_info)}); } if (ping_id != 0) { last_ping_container_id_ = container_id; diff --git a/td/mtproto/SessionConnection.h b/td/mtproto/SessionConnection.h index 6ca7524bf..8446fd1c0 100644 --- a/td/mtproto/SessionConnection.h +++ b/td/mtproto/SessionConnection.h @@ -11,6 +11,7 @@ #include "td/mtproto/RawConnection.h" #include "td/utils/buffer.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/format.h" #include "td/utils/logging.h" #include "td/utils/Named.h" @@ -22,7 +23,6 @@ #include "td/utils/StringBuilder.h" #include "td/utils/tl_parsers.h" -#include #include namespace td { @@ -176,10 +176,10 @@ class SessionConnection final vector to_resend_answer_; vector to_cancel_answer_; vector to_get_state_info_; - std::unordered_map service_queries_; + FlatHashMap service_queries_; // nobody cleans up this map. But it should be really small. - std::unordered_map> container_to_service_msg_; + FlatHashMap> container_to_service_msg_; double last_read_at_ = 0; double last_ping_at_ = 0; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 4cf82168d..664db1645 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -3441,13 +3441,15 @@ void ContactsManager::on_channel_participant_cache_timeout(ChannelId channel_id) auto &participants = channel_participants_it->second.participants_; auto min_access_date = G()->unix_time() - CHANNEL_PARTICIPANT_CACHE_TIME; - for (auto it = participants.begin(); it != participants.end();) { + vector to_delete_dialog_ids; + for (auto it = participants.begin(); it != participants.end(); ++it) { if (it->second.last_access_date_ < min_access_date) { - it = participants.erase(it); - } else { - ++it; + to_delete_dialog_ids.push_back(it->first); } } + for (auto dialog_id : to_delete_dialog_ids) { + participants.erase(dialog_id); + } if (participants.empty()) { channel_participants_.erase(channel_participants_it); diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 35c31f980..4c1cb5c89 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -48,7 +48,6 @@ #include #include -#include #include #include @@ -1742,7 +1741,7 @@ class ContactsManager final : public Actor { int32 last_access_date_ = 0; }; struct ChannelParticipants { - std::unordered_map participants_; + FlatHashMap participants_; }; FlatHashMap channel_participants_;