// // Copyright 2020 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include #include "src/core/ext/filters/client_channel/lb_policy/address_filtering.h" #include #include #include #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #define GRPC_ARG_HIERARCHICAL_PATH "grpc.internal.address.hierarchical_path" namespace grpc_core { const char* kHierarchicalPathAttributeKey = "hierarchical_path"; namespace { class HierarchicalPathAttribute : public ServerAddress::AttributeInterface { public: explicit HierarchicalPathAttribute(std::vector path) : path_(std::move(path)) {} std::unique_ptr Copy() const override { return absl::make_unique(path_); } int Cmp(const AttributeInterface* other) const override { const std::vector& other_path = static_cast(other)->path_; for (size_t i = 0; i < path_.size(); ++i) { if (other_path.size() == i) return 1; int r = path_[i].compare(other_path[i]); if (r != 0) return r; } if (other_path.size() > path_.size()) return -1; return 0; } std::string ToString() const override { return absl::StrCat("[", absl::StrJoin(path_, ", "), "]"); } const std::vector& path() const { return path_; } private: std::vector path_; }; } // namespace std::unique_ptr MakeHierarchicalPathAttribute(std::vector path) { return absl::make_unique(std::move(path)); } absl::StatusOr MakeHierarchicalAddressMap( const absl::StatusOr& addresses) { if (!addresses.ok()) return addresses.status(); HierarchicalAddressMap result; for (const ServerAddress& address : *addresses) { const HierarchicalPathAttribute* path_attribute = static_cast( address.GetAttribute(kHierarchicalPathAttributeKey)); if (path_attribute == nullptr) continue; const std::vector& path = path_attribute->path(); auto it = path.begin(); ServerAddressList& target_list = result[*it]; std::unique_ptr new_attribute; ++it; if (it != path.end()) { std::vector remaining_path(it, path.end()); new_attribute = absl::make_unique( std::move(remaining_path)); } target_list.emplace_back(address.WithAttribute( kHierarchicalPathAttributeKey, std::move(new_attribute))); } return result; } } // namespace grpc_core