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 "absl/strings/str_cat.h"
22 #include "absl/strings/str_join.h"
23
24 #include "src/core/lib/channel/channel_args.h"
25
26 #define GRPC_ARG_HIERARCHICAL_PATH "grpc.internal.address.hierarchical_path"
27
28 namespace grpc_core {
29
30 const char* kHierarchicalPathAttributeKey = "hierarchical_path";
31
32 namespace {
33
34 class HierarchicalPathAttribute : public ServerAddress::AttributeInterface {
35 public:
HierarchicalPathAttribute(std::vector<std::string> path)36 explicit HierarchicalPathAttribute(std::vector<std::string> path)
37 : path_(std::move(path)) {}
38
Copy() const39 std::unique_ptr<AttributeInterface> Copy() const override {
40 return absl::make_unique<HierarchicalPathAttribute>(path_);
41 }
42
Cmp(const AttributeInterface * other) const43 int Cmp(const AttributeInterface* other) const override {
44 const std::vector<std::string>& other_path =
45 static_cast<const HierarchicalPathAttribute*>(other)->path_;
46 for (size_t i = 0; i < path_.size(); ++i) {
47 if (other_path.size() == i) return 1;
48 int r = path_[i].compare(other_path[i]);
49 if (r != 0) return r;
50 }
51 if (other_path.size() > path_.size()) return -1;
52 return 0;
53 }
54
ToString() const55 std::string ToString() const override {
56 return absl::StrCat("[", absl::StrJoin(path_, ", "), "]");
57 }
58
path() const59 const std::vector<std::string>& path() const { return path_; }
60
61 private:
62 std::vector<std::string> path_;
63 };
64
65 } // namespace
66
67 std::unique_ptr<ServerAddress::AttributeInterface>
MakeHierarchicalPathAttribute(std::vector<std::string> path)68 MakeHierarchicalPathAttribute(std::vector<std::string> path) {
69 return absl::make_unique<HierarchicalPathAttribute>(std::move(path));
70 }
71
MakeHierarchicalAddressMap(const ServerAddressList & addresses)72 HierarchicalAddressMap MakeHierarchicalAddressMap(
73 const ServerAddressList& addresses) {
74 HierarchicalAddressMap result;
75 for (const ServerAddress& address : addresses) {
76 const HierarchicalPathAttribute* path_attribute =
77 static_cast<const HierarchicalPathAttribute*>(
78 address.GetAttribute(kHierarchicalPathAttributeKey));
79 if (path_attribute == nullptr) continue;
80 const std::vector<std::string>& path = path_attribute->path();
81 auto it = path.begin();
82 ServerAddressList& target_list = result[*it];
83 std::unique_ptr<HierarchicalPathAttribute> new_attribute;
84 ++it;
85 if (it != path.end()) {
86 std::vector<std::string> remaining_path(it, path.end());
87 new_attribute = absl::make_unique<HierarchicalPathAttribute>(
88 std::move(remaining_path));
89 }
90 target_list.emplace_back(address.WithAttribute(
91 kHierarchicalPathAttributeKey, std::move(new_attribute)));
92 }
93 return result;
94 }
95
96 } // namespace grpc_core
97