xref: /aosp_15_r20/external/grpc-grpc/src/core/load_balancing/endpoint_list.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 // Copyright 2015 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 #ifndef GRPC_SRC_CORE_LOAD_BALANCING_ENDPOINT_LIST_H
18 #define GRPC_SRC_CORE_LOAD_BALANCING_ENDPOINT_LIST_H
19 
20 #include <grpc/support/port_platform.h>
21 
22 #include <stdlib.h>
23 
24 #include <memory>
25 #include <utility>
26 #include <vector>
27 
28 #include "absl/functional/function_ref.h"
29 #include "absl/status/status.h"
30 #include "absl/types/optional.h"
31 
32 #include <grpc/impl/connectivity_state.h>
33 
34 #include "src/core/lib/channel/channel_args.h"
35 #include "src/core/lib/gprpp/debug_location.h"
36 #include "src/core/lib/gprpp/orphanable.h"
37 #include "src/core/lib/gprpp/ref_counted_ptr.h"
38 #include "src/core/lib/gprpp/work_serializer.h"
39 #include "src/core/lib/iomgr/resolved_address.h"
40 #include "src/core/load_balancing/lb_policy.h"
41 #include "src/core/load_balancing/subchannel_interface.h"
42 #include "src/core/resolver/endpoint_addresses.h"
43 
44 namespace grpc_core {
45 
46 // A list of endpoints for use in a petiole LB policy.  Each endpoint may
47 // have one or more addresses, which will be passed down to a pick_first
48 // child policy.
49 //
50 // To use this, a petiole policy must define its own subclass of both
51 // EndpointList and EndpointList::Endpoint, like so:
52 /*
53 class MyEndpointList : public EndpointList {
54  public:
55   MyEndpointList(RefCountedPtr<MyLbPolicy> lb_policy,
56                  EndpointAddressesIterator* endpoints,
57                  const ChannelArgs& args)
58       : EndpointList(std::move(lb_policy),
59                      GRPC_TRACE_FLAG_ENABLED(grpc_my_tracer)
60                          ? "MyEndpointList"
61                          : nullptr) {
62     Init(endpoints, args,
63          [&](RefCountedPtr<MyEndpointList> endpoint_list,
64              const EndpointAddresses& addresses, const ChannelArgs& args) {
65            return MakeOrphanable<MyEndpoint>(
66                std::move(endpoint_list), addresses, args,
67                policy<MyLbPolicy>()->work_serializer());
68          });
69   }
70 
71  private:
72   class MyEndpoint : public Endpoint {
73    public:
74     MyEndpoint(RefCountedPtr<MyEndpointList> endpoint_list,
75                const EndpointAddresses& address, const ChannelArgs& args,
76                std::shared_ptr<WorkSerializer> work_serializer)
77         : Endpoint(std::move(endpoint_list)) {
78       Init(addresses, args, std::move(work_serializer));
79     }
80 
81    private:
82     void OnStateUpdate(
83         absl::optional<grpc_connectivity_state> old_state,
84         grpc_connectivity_state new_state,
85         const absl::Status& status) override {
86       // ...handle connectivity state change...
87     }
88   };
89 
90   LoadBalancingPolicy::ChannelControlHelper* channel_control_helper()
91       const override {
92     return policy<MyLbPolicy>()->channel_control_helper();
93   }
94 };
95 */
96 // TODO(roth): Consider wrapping this in an LB policy subclass for petiole
97 // policies to inherit from.
98 class EndpointList : public InternallyRefCounted<EndpointList> {
99  public:
100   // An individual endpoint.
101   class Endpoint : public InternallyRefCounted<Endpoint> {
102    public:
~Endpoint()103     ~Endpoint() override { endpoint_list_.reset(DEBUG_LOCATION, "Endpoint"); }
104 
105     void Orphan() override;
106 
107     void ResetBackoffLocked();
108     void ExitIdleLocked();
109 
connectivity_state()110     absl::optional<grpc_connectivity_state> connectivity_state() const {
111       return connectivity_state_;
112     }
picker()113     RefCountedPtr<LoadBalancingPolicy::SubchannelPicker> picker() const {
114       return picker_;
115     }
116 
117    protected:
118     // We use two-phase initialization here to ensure that the vtable is
119     // initialized before we need to use it.  Subclass must invoke Init()
120     // from inside its ctor.
Endpoint(RefCountedPtr<EndpointList> endpoint_list)121     explicit Endpoint(RefCountedPtr<EndpointList> endpoint_list)
122         : endpoint_list_(std::move(endpoint_list)) {}
123 
124     void Init(const EndpointAddresses& addresses, const ChannelArgs& args,
125               std::shared_ptr<WorkSerializer> work_serializer);
126 
127     // Templated for convenience, to provide a short-hand for
128     // down-casting in the caller.
129     template <typename T>
endpoint_list()130     T* endpoint_list() const {
131       return static_cast<T*>(endpoint_list_.get());
132     }
133 
134     // Templated for convenience, to provide a short-hand for down-casting
135     // in the caller.
136     template <typename T>
policy()137     T* policy() const {
138       return endpoint_list_->policy<T>();
139     }
140 
141     // Returns the index of this endpoint within the EndpointList.
142     // Intended for trace logging.
143     size_t Index() const;
144 
145    private:
146     class Helper;
147 
148     // Called when the child policy reports a connectivity state update.
149     virtual void OnStateUpdate(
150         absl::optional<grpc_connectivity_state> old_state,
151         grpc_connectivity_state new_state, const absl::Status& status) = 0;
152 
153     // Called to create a subchannel.  Subclasses may override.
154     virtual RefCountedPtr<SubchannelInterface> CreateSubchannel(
155         const grpc_resolved_address& address,
156         const ChannelArgs& per_address_args, const ChannelArgs& args);
157 
158     RefCountedPtr<EndpointList> endpoint_list_;
159 
160     OrphanablePtr<LoadBalancingPolicy> child_policy_;
161     absl::optional<grpc_connectivity_state> connectivity_state_;
162     RefCountedPtr<LoadBalancingPolicy::SubchannelPicker> picker_;
163   };
164 
~EndpointList()165   ~EndpointList() override { policy_.reset(DEBUG_LOCATION, "EndpointList"); }
166 
Orphan()167   void Orphan() override {
168     endpoints_.clear();
169     Unref();
170   }
171 
size()172   size_t size() const { return endpoints_.size(); }
173 
endpoints()174   const std::vector<OrphanablePtr<Endpoint>>& endpoints() const {
175     return endpoints_;
176   }
177 
178   void ResetBackoffLocked();
179 
180  protected:
181   // We use two-phase initialization here to ensure that the vtable is
182   // initialized before we need to use it.  Subclass must invoke Init()
183   // from inside its ctor.
EndpointList(RefCountedPtr<LoadBalancingPolicy> policy,const char * tracer)184   EndpointList(RefCountedPtr<LoadBalancingPolicy> policy, const char* tracer)
185       : policy_(std::move(policy)), tracer_(tracer) {}
186 
187   void Init(EndpointAddressesIterator* endpoints, const ChannelArgs& args,
188             absl::FunctionRef<OrphanablePtr<Endpoint>(
189                 RefCountedPtr<EndpointList>, const EndpointAddresses&,
190                 const ChannelArgs&)>
191                 create_endpoint);
192 
193   // Templated for convenience, to provide a short-hand for down-casting
194   // in the caller.
195   template <typename T>
policy()196   T* policy() const {
197     return static_cast<T*>(policy_.get());
198   }
199 
200   // Returns true if all endpoints have seen their initial connectivity
201   // state notification.
AllEndpointsSeenInitialState()202   bool AllEndpointsSeenInitialState() const {
203     return num_endpoints_seen_initial_state_ == size();
204   }
205 
206  private:
207   // Returns the parent policy's helper.  Needed because the accessor
208   // method is protected on LoadBalancingPolicy.
209   virtual LoadBalancingPolicy::ChannelControlHelper* channel_control_helper()
210       const = 0;
211 
212   RefCountedPtr<LoadBalancingPolicy> policy_;
213   const char* tracer_;
214   std::vector<OrphanablePtr<Endpoint>> endpoints_;
215   size_t num_endpoints_seen_initial_state_ = 0;
216 };
217 
218 }  // namespace grpc_core
219 
220 #endif  // GRPC_SRC_CORE_LOAD_BALANCING_ENDPOINT_LIST_H
221