| // Copyright (c) 2022 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_MAP_H_ | |
| #define QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_MAP_H_ | |
| #include "absl/container/flat_hash_map.h" | |
| #include "quiche/quic/load_balancer/load_balancer_server_id.h" | |
| #include "quiche/quic/platform/api/quic_bug_tracker.h" | |
| namespace quic { | |
| // This class wraps an absl::flat_hash_map which associates server IDs to an | |
| // arbitrary type T. It validates that all server ids are of the same fixed | |
| // length. This might be used by a load balancer to connect a server ID with a | |
| // pool member data structure. | |
| template <typename T> | |
| class QUIC_EXPORT_PRIVATE LoadBalancerServerIdMap { | |
| public: | |
| // Returns a newly created pool for server IDs of length |server_id_len|, or | |
| // nullptr if |server_id_len| is invalid. | |
| static std::shared_ptr<LoadBalancerServerIdMap> Create( | |
| const uint8_t server_id_len); | |
| // Returns the entry associated with |server_id|, if present. For small |T|, | |
| // use Lookup. For large |T|, use LookupNoCopy. | |
| absl::optional<const T> Lookup(const LoadBalancerServerId server_id) const; | |
| const T* LookupNoCopy(const LoadBalancerServerId server_id) const; | |
| // Updates the table so that |value| is associated with |server_id|. Sets | |
| // QUIC_BUG if the length is incorrect for this map. | |
| void AddOrReplace(const LoadBalancerServerId server_id, T value); | |
| // Removes the entry associated with |server_id|. | |
| void Erase(const LoadBalancerServerId server_id) { | |
| server_id_table_.erase(server_id); | |
| } | |
| uint8_t server_id_len() const { return server_id_len_; } | |
| private: | |
| LoadBalancerServerIdMap(uint8_t server_id_len) | |
| : server_id_len_(server_id_len) {} | |
| const uint8_t server_id_len_; // All server IDs must be of this length. | |
| absl::flat_hash_map<LoadBalancerServerId, T> server_id_table_; | |
| }; | |
| template <typename T> | |
| std::shared_ptr<LoadBalancerServerIdMap<T>> LoadBalancerServerIdMap<T>::Create( | |
| const uint8_t server_id_len) { | |
| if (server_id_len == 0 || server_id_len > kLoadBalancerMaxServerIdLen) { | |
| QUIC_BUG(quic_bug_434893339_01) | |
| << "Tried to configure map with server ID length " | |
| << static_cast<int>(server_id_len); | |
| return nullptr; | |
| } | |
| return std::make_shared<LoadBalancerServerIdMap<T>>( | |
| LoadBalancerServerIdMap(server_id_len)); | |
| } | |
| template <typename T> | |
| absl::optional<const T> LoadBalancerServerIdMap<T>::Lookup( | |
| const LoadBalancerServerId server_id) const { | |
| if (server_id.length() != server_id_len_) { | |
| QUIC_BUG(quic_bug_434893339_02) | |
| << "Lookup with a " << static_cast<int>(server_id.length()) | |
| << " byte server ID, map requires " << static_cast<int>(server_id_len_); | |
| return absl::optional<T>(); | |
| } | |
| auto it = server_id_table_.find(server_id); | |
| return (it != server_id_table_.end()) ? it->second | |
| : absl::optional<const T>(); | |
| } | |
| template <typename T> | |
| const T* LoadBalancerServerIdMap<T>::LookupNoCopy( | |
| const LoadBalancerServerId server_id) const { | |
| if (server_id.length() != server_id_len_) { | |
| QUIC_BUG(quic_bug_434893339_02) | |
| << "Lookup with a " << static_cast<int>(server_id.length()) | |
| << " byte server ID, map requires " << static_cast<int>(server_id_len_); | |
| return nullptr; | |
| } | |
| auto it = server_id_table_.find(server_id); | |
| return (it != server_id_table_.end()) ? &it->second : nullptr; | |
| } | |
| template <typename T> | |
| void LoadBalancerServerIdMap<T>::AddOrReplace( | |
| const LoadBalancerServerId server_id, T value) { | |
| if (server_id.length() == server_id_len_) { | |
| server_id_table_[server_id] = value; | |
| } else { | |
| QUIC_BUG(quic_bug_434893339_03) | |
| << "Server ID of " << static_cast<int>(server_id.length()) | |
| << " bytes; this map requires " << static_cast<int>(server_id_len_); | |
| } | |
| } | |
| } // namespace quic | |
| #endif // QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_SERVER_ID_MAP_H_ |