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