• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //
3 // Copyright 2023 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include "test/cpp/interop/rpc_behavior_lb_policy.h"
20 
21 #include <grpc/support/port_platform.h>
22 
23 #include "absl/log/check.h"
24 #include "absl/strings/str_format.h"
25 #include "src/core/lib/iomgr/pollset_set.h"
26 #include "src/core/load_balancing/delegating_helper.h"
27 #include "src/core/util/json/json_args.h"
28 #include "src/core/util/json/json_object_loader.h"
29 
30 namespace grpc {
31 namespace testing {
32 
33 namespace {
34 
35 using grpc_core::CoreConfiguration;
36 using grpc_core::Json;
37 using grpc_core::JsonArgs;
38 using grpc_core::JsonLoaderInterface;
39 using grpc_core::LoadBalancingPolicy;
40 using grpc_core::OrphanablePtr;
41 using grpc_core::RefCountedPtr;
42 
43 constexpr absl::string_view kRpcBehaviorLbPolicyName =
44     "test.RpcBehaviorLoadBalancer";
45 
46 constexpr absl::string_view kRpcBehaviorMetadataKey = "rpc-behavior";
47 
48 class RpcBehaviorLbPolicyConfig : public LoadBalancingPolicy::Config {
49  public:
JsonLoader(const JsonArgs &)50   static JsonLoaderInterface* JsonLoader(const JsonArgs&) {
51     static const auto kJsonLoader =
52         grpc_core::JsonObjectLoader<RpcBehaviorLbPolicyConfig>()
53             .Field("rpcBehavior", &RpcBehaviorLbPolicyConfig::rpc_behavior_)
54             .Finish();
55     return kJsonLoader;
56   }
57 
rpc_behavior() const58   absl::string_view rpc_behavior() const { return rpc_behavior_; }
59 
60  private:
name() const61   absl::string_view name() const override { return kRpcBehaviorLbPolicyName; }
62 
63   std::string rpc_behavior_;
64 };
65 
66 class RpcBehaviorLbPolicy : public LoadBalancingPolicy {
67  public:
RpcBehaviorLbPolicy(Args args)68   explicit RpcBehaviorLbPolicy(Args args)
69       : LoadBalancingPolicy(std::move(args), /*initial_refcount=*/2) {
70     Args delegate_args;
71     delegate_args.work_serializer = work_serializer();
72     delegate_args.args = channel_args();
73     delegate_args.channel_control_helper =
74         std::make_unique<Helper>(RefCountedPtr<RpcBehaviorLbPolicy>(this));
75     delegate_ =
76         CoreConfiguration::Get().lb_policy_registry().CreateLoadBalancingPolicy(
77             "pick_first", std::move(delegate_args));
78     grpc_pollset_set_add_pollset_set(delegate_->interested_parties(),
79                                      interested_parties());
80   }
81 
82   ~RpcBehaviorLbPolicy() override = default;
83 
name() const84   absl::string_view name() const override { return kRpcBehaviorLbPolicyName; }
85 
UpdateLocked(UpdateArgs args)86   absl::Status UpdateLocked(UpdateArgs args) override {
87     auto config = args.config.TakeAsSubclass<RpcBehaviorLbPolicyConfig>();
88     rpc_behavior_ = std::string(config->rpc_behavior());
89     // Use correct config for the delegate load balancing policy
90     auto delegate_config =
91         CoreConfiguration::Get().lb_policy_registry().ParseLoadBalancingConfig(
92             grpc_core::Json::FromArray({grpc_core::Json::FromObject(
93                 {{std::string(delegate_->name()),
94                   grpc_core::Json::FromObject({})}})}));
95     CHECK_OK(delegate_config);
96     args.config = std::move(*delegate_config);
97     return delegate_->UpdateLocked(std::move(args));
98   }
99 
ExitIdleLocked()100   void ExitIdleLocked() override { delegate_->ExitIdleLocked(); }
101 
ResetBackoffLocked()102   void ResetBackoffLocked() override { delegate_->ResetBackoffLocked(); }
103 
104  private:
105   class Picker : public SubchannelPicker {
106    public:
Picker(RefCountedPtr<SubchannelPicker> delegate_picker,absl::string_view rpc_behavior)107     Picker(RefCountedPtr<SubchannelPicker> delegate_picker,
108            absl::string_view rpc_behavior)
109         : delegate_picker_(std::move(delegate_picker)),
110           rpc_behavior_(rpc_behavior) {}
111 
Pick(PickArgs args)112     PickResult Pick(PickArgs args) override {
113       // Do pick.
114       auto pick_result = delegate_picker_->Pick(args);
115       // Add metadata.
116       auto* complete_pick =
117           absl::get_if<PickResult::Complete>(&pick_result.result);
118       if (complete_pick != nullptr) {
119         complete_pick->metadata_mutations.Set(kRpcBehaviorMetadataKey,
120                                               rpc_behavior_);
121       }
122       // Return result.
123       return pick_result;
124     }
125 
126    private:
127     RefCountedPtr<SubchannelPicker> delegate_picker_;
128     std::string rpc_behavior_;
129   };
130 
131   class Helper
132       : public ParentOwningDelegatingChannelControlHelper<RpcBehaviorLbPolicy> {
133    public:
Helper(RefCountedPtr<RpcBehaviorLbPolicy> parent)134     explicit Helper(RefCountedPtr<RpcBehaviorLbPolicy> parent)
135         : ParentOwningDelegatingChannelControlHelper(std::move(parent)) {}
136 
UpdateState(grpc_connectivity_state state,const absl::Status & status,RefCountedPtr<SubchannelPicker> picker)137     void UpdateState(grpc_connectivity_state state, const absl::Status& status,
138                      RefCountedPtr<SubchannelPicker> picker) override {
139       parent_helper()->UpdateState(
140           state, status,
141           grpc_core::MakeRefCounted<Picker>(std::move(picker),
142                                             parent()->rpc_behavior_));
143     }
144   };
145 
ShutdownLocked()146   void ShutdownLocked() override {
147     grpc_pollset_set_del_pollset_set(delegate_->interested_parties(),
148                                      interested_parties());
149     delegate_.reset();
150   }
151 
152   OrphanablePtr<LoadBalancingPolicy> delegate_;
153   std::string rpc_behavior_;
154 };
155 
156 class RpcBehaviorLbPolicyFactory
157     : public grpc_core::LoadBalancingPolicyFactory {
158  private:
name() const159   absl::string_view name() const override { return kRpcBehaviorLbPolicyName; }
160 
CreateLoadBalancingPolicy(LoadBalancingPolicy::Args args) const161   grpc_core::OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
162       LoadBalancingPolicy::Args args) const override {
163     return grpc_core::MakeOrphanable<RpcBehaviorLbPolicy>(std::move(args));
164   }
165 
166   absl::StatusOr<RefCountedPtr<LoadBalancingPolicy::Config>>
ParseLoadBalancingConfig(const Json & json) const167   ParseLoadBalancingConfig(const Json& json) const override {
168     return grpc_core::LoadFromJson<RefCountedPtr<RpcBehaviorLbPolicyConfig>>(
169         json, JsonArgs(), "errors validating LB policy config");
170   }
171 };
172 }  // namespace
173 
RegisterRpcBehaviorLbPolicy(grpc_core::CoreConfiguration::Builder * builder)174 void RegisterRpcBehaviorLbPolicy(
175     grpc_core::CoreConfiguration::Builder* builder) {
176   builder->lb_policy_registry()->RegisterLoadBalancingPolicyFactory(
177       std::make_unique<RpcBehaviorLbPolicyFactory>());
178 }
179 
180 }  // namespace testing
181 }  // namespace grpc
182