xref: /aosp_15_r20/external/grpc-grpc/test/cpp/interop/rpc_behavior_lb_policy.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 "absl/strings/str_format.h"
22 
23 #include <grpc/support/port_platform.h>
24 
25 #include "src/core/lib/iomgr/pollset_set.h"
26 #include "src/core/lib/json/json_args.h"
27 #include "src/core/lib/json/json_object_loader.h"
28 #include "src/core/load_balancing/delegating_helper.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     GPR_ASSERT(delegate_config.ok());
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       char* rpc_behavior_copy = static_cast<char*>(
114           args.call_state->Alloc(rpc_behavior_.length() + 1));
115       strcpy(rpc_behavior_copy, rpc_behavior_.c_str());
116       args.initial_metadata->Add(kRpcBehaviorMetadataKey, rpc_behavior_copy);
117       // Do pick.
118       return delegate_picker_->Pick(args);
119     }
120 
121    private:
122     RefCountedPtr<SubchannelPicker> delegate_picker_;
123     std::string rpc_behavior_;
124   };
125 
126   class Helper
127       : public ParentOwningDelegatingChannelControlHelper<RpcBehaviorLbPolicy> {
128    public:
Helper(RefCountedPtr<RpcBehaviorLbPolicy> parent)129     explicit Helper(RefCountedPtr<RpcBehaviorLbPolicy> parent)
130         : ParentOwningDelegatingChannelControlHelper(std::move(parent)) {}
131 
UpdateState(grpc_connectivity_state state,const absl::Status & status,RefCountedPtr<SubchannelPicker> picker)132     void UpdateState(grpc_connectivity_state state, const absl::Status& status,
133                      RefCountedPtr<SubchannelPicker> picker) override {
134       parent_helper()->UpdateState(
135           state, status,
136           grpc_core::MakeRefCounted<Picker>(std::move(picker),
137                                             parent()->rpc_behavior_));
138     }
139   };
140 
ShutdownLocked()141   void ShutdownLocked() override {
142     grpc_pollset_set_del_pollset_set(delegate_->interested_parties(),
143                                      interested_parties());
144     delegate_.reset();
145   }
146 
147   OrphanablePtr<LoadBalancingPolicy> delegate_;
148   std::string rpc_behavior_;
149 };
150 
151 class RpcBehaviorLbPolicyFactory
152     : public grpc_core::LoadBalancingPolicyFactory {
153  private:
name() const154   absl::string_view name() const override { return kRpcBehaviorLbPolicyName; }
155 
CreateLoadBalancingPolicy(LoadBalancingPolicy::Args args) const156   grpc_core::OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
157       LoadBalancingPolicy::Args args) const override {
158     return grpc_core::MakeOrphanable<RpcBehaviorLbPolicy>(std::move(args));
159   }
160 
161   absl::StatusOr<RefCountedPtr<LoadBalancingPolicy::Config>>
ParseLoadBalancingConfig(const Json & json) const162   ParseLoadBalancingConfig(const Json& json) const override {
163     return grpc_core::LoadFromJson<RefCountedPtr<RpcBehaviorLbPolicyConfig>>(
164         json, JsonArgs(), "errors validating LB policy config");
165   }
166 };
167 }  // namespace
168 
RegisterRpcBehaviorLbPolicy(grpc_core::CoreConfiguration::Builder * builder)169 void RegisterRpcBehaviorLbPolicy(
170     grpc_core::CoreConfiguration::Builder* builder) {
171   builder->lb_policy_registry()->RegisterLoadBalancingPolicyFactory(
172       std::make_unique<RpcBehaviorLbPolicyFactory>());
173 }
174 
175 }  // namespace testing
176 }  // namespace grpc
177