1 //
2 // Copyright 2020 gRPC authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include <grpc/support/port_platform.h>
18
19 #include "src/core/ext/filters/client_channel/lb_policy/address_filtering.h"
20
21 #include <stddef.h>
22
23 #include <algorithm>
24 #include <utility>
25
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_join.h"
28
29 #define GRPC_ARG_HIERARCHICAL_PATH "grpc.internal.address.hierarchical_path"
30
31 namespace grpc_core {
32
33 const char* kHierarchicalPathAttributeKey = "hierarchical_path";
34
35 namespace {
36
37 class HierarchicalPathAttribute : public ServerAddress::AttributeInterface {
38 public:
HierarchicalPathAttribute(std::vector<std::string> path)39 explicit HierarchicalPathAttribute(std::vector<std::string> path)
40 : path_(std::move(path)) {}
41
Copy() const42 std::unique_ptr<AttributeInterface> Copy() const override {
43 return std::make_unique<HierarchicalPathAttribute>(path_);
44 }
45
Cmp(const AttributeInterface * other) const46 int Cmp(const AttributeInterface* other) const override {
47 const std::vector<std::string>& other_path =
48 static_cast<const HierarchicalPathAttribute*>(other)->path_;
49 for (size_t i = 0; i < path_.size(); ++i) {
50 if (other_path.size() == i) return 1;
51 int r = path_[i].compare(other_path[i]);
52 if (r != 0) return r;
53 }
54 if (other_path.size() > path_.size()) return -1;
55 return 0;
56 }
57
ToString() const58 std::string ToString() const override {
59 return absl::StrCat("[", absl::StrJoin(path_, ", "), "]");
60 }
61
path() const62 const std::vector<std::string>& path() const { return path_; }
63
64 private:
65 std::vector<std::string> path_;
66 };
67
68 } // namespace
69
70 std::unique_ptr<ServerAddress::AttributeInterface>
MakeHierarchicalPathAttribute(std::vector<std::string> path)71 MakeHierarchicalPathAttribute(std::vector<std::string> path) {
72 return std::make_unique<HierarchicalPathAttribute>(std::move(path));
73 }
74
MakeHierarchicalAddressMap(const absl::StatusOr<ServerAddressList> & addresses)75 absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap(
76 const absl::StatusOr<ServerAddressList>& addresses) {
77 if (!addresses.ok()) return addresses.status();
78 HierarchicalAddressMap result;
79 for (const ServerAddress& address : *addresses) {
80 const HierarchicalPathAttribute* path_attribute =
81 static_cast<const HierarchicalPathAttribute*>(
82 address.GetAttribute(kHierarchicalPathAttributeKey));
83 if (path_attribute == nullptr) continue;
84 const std::vector<std::string>& path = path_attribute->path();
85 auto it = path.begin();
86 ServerAddressList& target_list = result[*it];
87 std::unique_ptr<HierarchicalPathAttribute> new_attribute;
88 ++it;
89 if (it != path.end()) {
90 std::vector<std::string> remaining_path(it, path.end());
91 new_attribute = std::make_unique<HierarchicalPathAttribute>(
92 std::move(remaining_path));
93 }
94 target_list.emplace_back(address.WithAttribute(
95 kHierarchicalPathAttributeKey, std::move(new_attribute)));
96 }
97 return result;
98 }
99
100 } // namespace grpc_core
101