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