blob: 98f85ae52eb8a97f8c8891992f0fb1e72019bb94 [file] [log] [blame]
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2016 gRPC authors.
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070016 *
17 */
18
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070019/** Implementation of the gRPC LB policy.
20 *
David Garcia Quintas43339842016-07-18 12:56:09 -070021 * This policy takes as input a set of resolved addresses {a1..an} for which the
22 * LB set was set (it's the resolver's responsibility to ensure this). That is
23 * to say, {a1..an} represent a collection of LB servers.
24 *
25 * An internal channel (\a glb_lb_policy.lb_channel) is created over {a1..an}.
26 * This channel behaves just like a regular channel. In particular, the
27 * constructed URI over the addresses a1..an will use the default pick first
28 * policy to select from this list of LB server backends.
29 *
David Garcia Quintas41bef452016-07-28 19:19:58 -070030 * The first time the policy gets a request for a pick, a ping, or to exit the
David Garcia Quintas98da61b2016-10-29 08:46:31 +020031 * idle state, \a query_for_backends_locked() is called. This function sets up
32 * and initiates the internal communication with the LB server. In particular,
33 * it's responsible for instantiating the internal *streaming* call to the LB
34 * server (whichever address from {a1..an} pick-first chose). This call is
David Garcia Quintas7ec29132016-11-01 04:09:05 +010035 * serviced by two callbacks, \a lb_on_server_status_received and \a
36 * lb_on_response_received. The former will be called when the call to the LB
37 * server completes. This can happen if the LB server closes the connection or
38 * if this policy itself cancels the call (for example because it's shutting
David Garcia Quintas246c5642016-11-01 11:16:52 -070039 * down). If the internal call times out, the usual behavior of pick-first
David Garcia Quintas7ec29132016-11-01 04:09:05 +010040 * applies, continuing to pick from the list {a1..an}.
David Garcia Quintas43339842016-07-18 12:56:09 -070041 *
David Garcia Quintas98da61b2016-10-29 08:46:31 +020042 * Upon sucesss, the incoming \a LoadBalancingResponse is processed by \a
43 * res_recv. An invalid one results in the termination of the streaming call. A
44 * new streaming call should be created if possible, failing the original call
45 * otherwise. For a valid \a LoadBalancingResponse, the server list of actual
46 * backends is extracted. A Round Robin policy will be created from this list.
47 * There are two possible scenarios:
David Garcia Quintas43339842016-07-18 12:56:09 -070048 *
49 * 1. This is the first server list received. There was no previous instance of
David Garcia Quintas90712d52016-10-13 19:33:04 -070050 * the Round Robin policy. \a rr_handover_locked() will instantiate the RR
51 * policy and perform all the pending operations over it.
David Garcia Quintas43339842016-07-18 12:56:09 -070052 * 2. There's already a RR policy instance active. We need to introduce the new
53 * one build from the new serverlist, but taking care not to disrupt the
54 * operations in progress over the old RR instance. This is done by
55 * decreasing the reference count on the old policy. The moment no more
56 * references are held on the old RR policy, it'll be destroyed and \a
David Garcia Quintas348cfdb2016-08-19 12:19:43 -070057 * glb_rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN
58 * state. At this point we can transition to a new RR instance safely, which
David Garcia Quintas90712d52016-10-13 19:33:04 -070059 * is done once again via \a rr_handover_locked().
David Garcia Quintas43339842016-07-18 12:56:09 -070060 *
61 *
62 * Once a RR policy instance is in place (and getting updated as described),
63 * calls to for a pick, a ping or a cancellation will be serviced right away by
64 * forwarding them to the RR instance. Any time there's no RR policy available
David Garcia Quintas7ec29132016-11-01 04:09:05 +010065 * (ie, right after the creation of the gRPCLB policy, if an empty serverlist is
66 * received, etc), pick/ping requests are added to a list of pending picks/pings
67 * to be flushed and serviced as part of \a rr_handover_locked() the moment the
68 * RR policy instance becomes available.
David Garcia Quintas43339842016-07-18 12:56:09 -070069 *
70 * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the
71 * high level design and details. */
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070072
73/* TODO(dgq):
74 * - Implement LB service forwarding (point 2c. in the doc's diagram).
75 */
76
murgatroid99085f9af2016-10-24 09:55:44 -070077/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
78 using that endpoint. Because of various transitive includes in uv.h,
79 including windows.h on Windows, uv.h must be included before other system
80 headers. Therefore, sockaddr.h must always be included first */
murgatroid997871f732016-09-23 13:49:05 -070081#include "src/core/lib/iomgr/sockaddr.h"
82
Yash Tibrewalfcd26bc2017-09-25 15:08:28 -070083#include <inttypes.h>
Mark D. Roth64d922a2017-05-03 12:52:04 -070084#include <limits.h>
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -070085#include <string.h>
86
87#include <grpc/byte_buffer_reader.h>
88#include <grpc/grpc.h>
89#include <grpc/support/alloc.h>
90#include <grpc/support/host_port.h>
91#include <grpc/support/string_util.h>
David Garcia Quintas69099222016-10-03 11:28:37 -070092#include <grpc/support/time.h>
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -070093
Craig Tiller9eb0fde2017-03-31 16:59:30 -070094#include "src/core/ext/filters/client_channel/client_channel.h"
95#include "src/core/ext/filters/client_channel/client_channel_factory.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -070096#include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
Craig Tiller9eb0fde2017-03-31 16:59:30 -070097#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
98#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -070099#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h"
Craig Tiller9eb0fde2017-03-31 16:59:30 -0700100#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h"
Craig Tillerd52e22f2017-04-02 16:22:52 -0700101#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
102#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
103#include "src/core/ext/filters/client_channel/parse_address.h"
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700104#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
Juanli Shen6502ecc2017-09-13 13:10:54 -0700105#include "src/core/ext/filters/client_channel/subchannel_index.h"
Craig Tillerc0df1c02017-07-17 16:12:33 -0700106#include "src/core/lib/backoff/backoff.h"
Mark D. Roth046cf762016-09-26 11:13:51 -0700107#include "src/core/lib/channel/channel_args.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -0700108#include "src/core/lib/channel/channel_stack.h"
Craig Tiller2400bf52017-02-09 16:25:19 -0800109#include "src/core/lib/iomgr/combiner.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200110#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700111#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200112#include "src/core/lib/iomgr/timer.h"
David Garcia Quintas01291502017-02-07 13:26:41 -0800113#include "src/core/lib/slice/slice_hash_table.h"
Craig Tiller18b4ba32016-11-09 15:23:42 -0800114#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -0700115#include "src/core/lib/slice/slice_string_helpers.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700116#include "src/core/lib/support/string.h"
117#include "src/core/lib/surface/call.h"
118#include "src/core/lib/surface/channel.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -0700119#include "src/core/lib/surface/channel_init.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700120#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700121
David Garcia Quintas1edfb952016-11-22 17:15:34 -0800122#define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20
123#define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1
124#define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6
125#define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
126#define GRPC_GRPCLB_RECONNECT_JITTER 0.2
Juanli Shenfe408152017-09-27 12:27:20 -0700127#define GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS 10000
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200128
ncteisen06bce6e2017-07-10 07:58:49 -0700129grpc_tracer_flag grpc_lb_glb_trace = GRPC_TRACER_INITIALIZER(false, "glb");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700130
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700131/* add lb_token of selected subchannel (address) to the call's initial
132 * metadata */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700133static grpc_error* initial_metadata_add_lb_token(
134 grpc_exec_ctx* exec_ctx, grpc_metadata_batch* initial_metadata,
135 grpc_linked_mdelem* lb_token_mdelem_storage, grpc_mdelem lb_token) {
Craig Tiller4782d922017-11-10 09:53:21 -0800136 GPR_ASSERT(lb_token_mdelem_storage != nullptr);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800137 GPR_ASSERT(!GRPC_MDISNULL(lb_token));
138 return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
139 lb_token_mdelem_storage, lb_token);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700140}
141
Craig Tillerbaa14a92017-11-03 09:09:36 -0700142static void destroy_client_stats(void* arg) {
143 grpc_grpclb_client_stats_unref((grpc_grpclb_client_stats*)arg);
Mark D. Roth09e458c2017-05-02 08:13:26 -0700144}
145
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700146typedef struct wrapped_rr_closure_arg {
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700147 /* the closure instance using this struct as argument */
148 grpc_closure wrapper_closure;
149
David Garcia Quintas43339842016-07-18 12:56:09 -0700150 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
151 * calls against the internal RR instance, respectively. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700152 grpc_closure* wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700153
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700154 /* the pick's initial metadata, kept in order to append the LB token for the
155 * pick */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700156 grpc_metadata_batch* initial_metadata;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700157
158 /* the picked target, used to determine which LB token to add to the pick's
159 * initial metadata */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700160 grpc_connected_subchannel** target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700161
Mark D. Roth09e458c2017-05-02 08:13:26 -0700162 /* the context to be populated for the subchannel call */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700163 grpc_call_context_element* context;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700164
165 /* Stats for client-side load reporting. Note that this holds a
166 * reference, which must be either passed on via context or unreffed. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700167 grpc_grpclb_client_stats* client_stats;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700168
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700169 /* the LB token associated with the pick */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800170 grpc_mdelem lb_token;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700171
172 /* storage for the lb token initial metadata mdelem */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700173 grpc_linked_mdelem* lb_token_mdelem_storage;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700174
David Garcia Quintas43339842016-07-18 12:56:09 -0700175 /* The RR instance related to the closure */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700176 grpc_lb_policy* rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700177
David Garcia Quintas2b372e02017-11-09 14:15:59 -0800178 /* The grpclb instance that created the wrapping. This instance is not owned,
David Garcia Quintas59607902017-11-09 14:39:59 -0800179 * reference counts are untouched. It's used only for logging purposes. */
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800180 grpc_lb_policy* glb_policy;
181
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700182 /* heap memory to be freed upon closure execution. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700183 void* free_when_done;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700184} wrapped_rr_closure_arg;
185
186/* The \a on_complete closure passed as part of the pick requires keeping a
187 * reference to its associated round robin instance. We wrap this closure in
188 * order to unref the round robin instance upon its invocation */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700189static void wrapped_rr_closure(grpc_exec_ctx* exec_ctx, void* arg,
190 grpc_error* error) {
191 wrapped_rr_closure_arg* wc_arg = (wrapped_rr_closure_arg*)arg;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700192
Craig Tiller4782d922017-11-10 09:53:21 -0800193 GPR_ASSERT(wc_arg->wrapped_closure != nullptr);
ncteisen969b46e2017-06-08 14:57:11 -0700194 GRPC_CLOSURE_SCHED(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200195
Craig Tiller4782d922017-11-10 09:53:21 -0800196 if (wc_arg->rr_policy != nullptr) {
David Garcia Quintas6493a732016-11-22 10:25:52 -0800197 /* if *target is NULL, no pick has been made by the RR policy (eg, all
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700198 * addresses failed to connect). There won't be any user_data/token
199 * available */
Craig Tiller4782d922017-11-10 09:53:21 -0800200 if (*wc_arg->target != nullptr) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800201 if (!GRPC_MDISNULL(wc_arg->lb_token)) {
202 initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800203 wc_arg->lb_token_mdelem_storage,
204 GRPC_MDELEM_REF(wc_arg->lb_token));
205 } else {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800206 gpr_log(
207 GPR_ERROR,
208 "[grpclb %p] No LB token for connected subchannel pick %p (from RR "
209 "instance %p).",
210 wc_arg->glb_policy, *wc_arg->target, wc_arg->rr_policy);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800211 abort();
212 }
Mark D. Roth09e458c2017-05-02 08:13:26 -0700213 // Pass on client stats via context. Passes ownership of the reference.
Craig Tiller4782d922017-11-10 09:53:21 -0800214 GPR_ASSERT(wc_arg->client_stats != nullptr);
Mark D. Roth09e458c2017-05-02 08:13:26 -0700215 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
216 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
217 } else {
218 grpc_grpclb_client_stats_unref(wc_arg->client_stats);
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700219 }
Craig Tiller84f75d42017-05-03 13:06:35 -0700220 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800221 gpr_log(GPR_INFO, "[grpclb %p] Unreffing RR %p", wc_arg->glb_policy,
222 wc_arg->rr_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200223 }
224 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700225 }
Craig Tiller4782d922017-11-10 09:53:21 -0800226 GPR_ASSERT(wc_arg->free_when_done != nullptr);
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700227 gpr_free(wc_arg->free_when_done);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700228}
229
David Garcia Quintasea11d162016-07-14 17:27:28 -0700230/* Linked list of pending pick requests. It stores all information needed to
231 * eventually call (Round Robin's) pick() on them. They mainly stay pending
232 * waiting for the RR policy to be created/updated.
233 *
234 * One particularity is the wrapping of the user-provided \a on_complete closure
235 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
236 * order to correctly unref the RR policy instance upon completion of the pick.
237 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700238typedef struct pending_pick {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700239 struct pending_pick* next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700240
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700241 /* original pick()'s arguments */
242 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700243
244 /* output argument where to store the pick()ed connected subchannel, or NULL
245 * upon error. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700246 grpc_connected_subchannel** target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700247
David Garcia Quintas43339842016-07-18 12:56:09 -0700248 /* args for wrapped_on_complete */
249 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700250} pending_pick;
251
Craig Tillerbaa14a92017-11-03 09:09:36 -0700252static void add_pending_pick(pending_pick** root,
253 const grpc_lb_policy_pick_args* pick_args,
254 grpc_connected_subchannel** target,
255 grpc_call_context_element* context,
256 grpc_closure* on_complete) {
257 pending_pick* pp = (pending_pick*)gpr_zalloc(sizeof(*pp));
David Garcia Quintas65318262016-07-29 13:43:38 -0700258 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700259 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700260 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700261 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700262 pp->wrapped_on_complete_arg.target = target;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700263 pp->wrapped_on_complete_arg.context = context;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700264 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
265 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
266 pick_args->lb_token_mdelem_storage;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700267 pp->wrapped_on_complete_arg.free_when_done = pp;
ncteisen969b46e2017-06-08 14:57:11 -0700268 GRPC_CLOSURE_INIT(&pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800269 wrapped_rr_closure, &pp->wrapped_on_complete_arg,
270 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700271 *root = pp;
272}
273
David Garcia Quintasea11d162016-07-14 17:27:28 -0700274/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700275typedef struct pending_ping {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700276 struct pending_ping* next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700277
David Garcia Quintas43339842016-07-18 12:56:09 -0700278 /* args for wrapped_notify */
279 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700280} pending_ping;
281
Craig Tillerbaa14a92017-11-03 09:09:36 -0700282static void add_pending_ping(pending_ping** root, grpc_closure* notify) {
283 pending_ping* pping = (pending_ping*)gpr_zalloc(sizeof(*pping));
David Garcia Quintas65318262016-07-29 13:43:38 -0700284 pping->wrapped_notify_arg.wrapped_closure = notify;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700285 pping->wrapped_notify_arg.free_when_done = pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700286 pping->next = *root;
ncteisen969b46e2017-06-08 14:57:11 -0700287 GRPC_CLOSURE_INIT(&pping->wrapped_notify_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800288 wrapped_rr_closure, &pping->wrapped_notify_arg,
289 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700290 *root = pping;
291}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700292
David Garcia Quintas8d489112016-07-29 15:20:42 -0700293/*
294 * glb_lb_policy
295 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700296typedef struct rr_connectivity_data rr_connectivity_data;
Yash Tibrewalbc130da2017-09-12 22:44:08 -0700297
David Garcia Quintas65318262016-07-29 13:43:38 -0700298typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700299 /** base policy: must be first */
300 grpc_lb_policy base;
301
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700302 /** who the client is trying to communicate with */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700303 const char* server_name;
304 grpc_client_channel_factory* cc_factory;
305 grpc_channel_args* args;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700306
Mark D. Roth64d922a2017-05-03 12:52:04 -0700307 /** timeout in milliseconds for the LB call. 0 means no deadline. */
308 int lb_call_timeout_ms;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700309
Juanli Shenfe408152017-09-27 12:27:20 -0700310 /** timeout in milliseconds for before using fallback backend addresses.
311 * 0 means not using fallback. */
312 int lb_fallback_timeout_ms;
313
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700314 /** for communicating with the LB server */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700315 grpc_channel* lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700316
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700317 /** response generator to inject address updates into \a lb_channel */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700318 grpc_fake_resolver_response_generator* response_generator;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700319
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700320 /** the RR policy to use of the backend servers returned by the LB server */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700321 grpc_lb_policy* rr_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700322
323 bool started_picking;
324
325 /** our connectivity state tracker */
326 grpc_connectivity_state_tracker state_tracker;
327
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700328 /** connectivity state of the LB channel */
329 grpc_connectivity_state lb_channel_connectivity;
330
David Garcia Quintasea11d162016-07-14 17:27:28 -0700331 /** stores the deserialized response from the LB. May be NULL until one such
332 * response has arrived. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700333 grpc_grpclb_serverlist* serverlist;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700334
Mark D. Rothd7389b42017-05-17 12:22:17 -0700335 /** Index into serverlist for next pick.
336 * If the server at this index is a drop, we return a drop.
337 * Otherwise, we delegate to the RR policy. */
338 size_t serverlist_index;
339
Juanli Shenfe408152017-09-27 12:27:20 -0700340 /** stores the backend addresses from the resolver */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700341 grpc_lb_addresses* fallback_backend_addresses;
Juanli Shenfe408152017-09-27 12:27:20 -0700342
David Garcia Quintasea11d162016-07-14 17:27:28 -0700343 /** list of picks that are waiting on RR's policy connectivity */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700344 pending_pick* pending_picks;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700345
David Garcia Quintasea11d162016-07-14 17:27:28 -0700346 /** list of pings that are waiting on RR's policy connectivity */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700347 pending_ping* pending_pings;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700348
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200349 bool shutting_down;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700350
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700351 /** are we currently updating lb_call? */
352 bool updating_lb_call;
353
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700354 /** are we already watching the LB channel's connectivity? */
355 bool watching_lb_channel;
356
357 /** is \a lb_call_retry_timer active? */
358 bool retry_timer_active;
359
Juanli Shenfe408152017-09-27 12:27:20 -0700360 /** is \a lb_fallback_timer active? */
361 bool fallback_timer_active;
362
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700363 /** called upon changes to the LB channel's connectivity. */
364 grpc_closure lb_channel_on_connectivity_changed;
365
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200366 /************************************************************/
367 /* client data associated with the LB server communication */
368 /************************************************************/
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100369 /* Status from the LB server has been received. This signals the end of the LB
370 * call. */
371 grpc_closure lb_on_server_status_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200372
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100373 /* A response from the LB server has been received. Process it */
374 grpc_closure lb_on_response_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200375
Masood Malekghassemib5b43722017-01-05 15:07:26 -0800376 /* LB call retry timer callback. */
377 grpc_closure lb_on_call_retry;
378
Juanli Shenfe408152017-09-27 12:27:20 -0700379 /* LB fallback timer callback. */
380 grpc_closure lb_on_fallback;
381
Craig Tillerbaa14a92017-11-03 09:09:36 -0700382 grpc_call* lb_call; /* streaming call to the LB server, */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200383
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100384 grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */
385 grpc_metadata_array
386 lb_trailing_metadata_recv; /* trailing MD from LB server */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200387
388 /* what's being sent to the LB server. Note that its value may vary if the LB
389 * server indicates a redirect. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700390 grpc_byte_buffer* lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200391
David Garcia Quintas246c5642016-11-01 11:16:52 -0700392 /* response the LB server, if any. Processed in lb_on_response_received() */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700393 grpc_byte_buffer* lb_response_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200394
David Garcia Quintas246c5642016-11-01 11:16:52 -0700395 /* call status code and details, set in lb_on_server_status_received() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200396 grpc_status_code lb_call_status;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800397 grpc_slice lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200398
399 /** LB call retry backoff state */
Craig Tillerc0df1c02017-07-17 16:12:33 -0700400 grpc_backoff lb_call_backoff_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200401
402 /** LB call retry timer */
403 grpc_timer lb_call_retry_timer;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700404
Juanli Shenfe408152017-09-27 12:27:20 -0700405 /** LB fallback timer */
406 grpc_timer lb_fallback_timer;
407
Mark D. Roth09e458c2017-05-02 08:13:26 -0700408 bool seen_initial_response;
409
410 /* Stats for client-side load reporting. Should be unreffed and
411 * recreated whenever lb_call is replaced. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700412 grpc_grpclb_client_stats* client_stats;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700413 /* Interval and timer for next client load report. */
Craig Tillerc0df1c02017-07-17 16:12:33 -0700414 grpc_millis client_stats_report_interval;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700415 grpc_timer client_load_report_timer;
416 bool client_load_report_timer_pending;
417 bool last_client_load_report_counters_were_zero;
418 /* Closure used for either the load report timer or the callback for
419 * completion of sending the load report. */
420 grpc_closure client_load_report_closure;
421 /* Client load report message payload. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700422 grpc_byte_buffer* client_load_report_payload;
David Garcia Quintas65318262016-07-29 13:43:38 -0700423} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700424
David Garcia Quintas65318262016-07-29 13:43:38 -0700425/* Keeps track and reacts to changes in connectivity of the RR instance */
426struct rr_connectivity_data {
427 grpc_closure on_change;
428 grpc_connectivity_state state;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700429 glb_lb_policy* glb_policy;
David Garcia Quintas65318262016-07-29 13:43:38 -0700430};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700431
Craig Tillerbaa14a92017-11-03 09:09:36 -0700432static bool is_server_valid(const grpc_grpclb_server* server, size_t idx,
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700433 bool log) {
Mark D. Rothe7751802017-07-27 12:31:45 -0700434 if (server->drop) return false;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700435 const grpc_grpclb_ip_address* ip = &server->ip_address;
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700436 if (server->port >> 16 != 0) {
437 if (log) {
438 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200439 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
440 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700441 }
442 return false;
443 }
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700444 if (ip->size != 4 && ip->size != 16) {
445 if (log) {
446 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200447 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700448 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200449 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700450 }
451 return false;
452 }
453 return true;
454}
455
Mark D. Roth16883a32016-10-21 10:30:58 -0700456/* vtable for LB tokens in grpc_lb_addresses. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700457static void* lb_token_copy(void* token) {
Craig Tiller4ac2b8e2017-11-10 14:14:17 -0800458 return token == nullptr
459 ? nullptr
Craig Tillerbaa14a92017-11-03 09:09:36 -0700460 : (void*)GRPC_MDELEM_REF(grpc_mdelem{(uintptr_t)token}).payload;
Mark D. Roth16883a32016-10-21 10:30:58 -0700461}
Craig Tillerbaa14a92017-11-03 09:09:36 -0700462static void lb_token_destroy(grpc_exec_ctx* exec_ctx, void* token) {
Craig Tiller4782d922017-11-10 09:53:21 -0800463 if (token != nullptr) {
Yash Tibrewald8b84a22017-09-25 13:38:03 -0700464 GRPC_MDELEM_UNREF(exec_ctx, grpc_mdelem{(uintptr_t)token});
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800465 }
Mark D. Roth16883a32016-10-21 10:30:58 -0700466}
Craig Tillerbaa14a92017-11-03 09:09:36 -0700467static int lb_token_cmp(void* token1, void* token2) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700468 if (token1 > token2) return 1;
469 if (token1 < token2) return -1;
470 return 0;
471}
472static const grpc_lb_user_data_vtable lb_token_vtable = {
473 lb_token_copy, lb_token_destroy, lb_token_cmp};
474
Craig Tillerbaa14a92017-11-03 09:09:36 -0700475static void parse_server(const grpc_grpclb_server* server,
476 grpc_resolved_address* addr) {
Mark D. Rothd7389b42017-05-17 12:22:17 -0700477 memset(addr, 0, sizeof(*addr));
Mark D. Rothe7751802017-07-27 12:31:45 -0700478 if (server->drop) return;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100479 const uint16_t netorder_port = htons((uint16_t)server->port);
480 /* the addresses are given in binary format (a in(6)_addr struct) in
481 * server->ip_address.bytes. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700482 const grpc_grpclb_ip_address* ip = &server->ip_address;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100483 if (ip->size == 4) {
484 addr->len = sizeof(struct sockaddr_in);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700485 struct sockaddr_in* addr4 = (struct sockaddr_in*)&addr->addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100486 addr4->sin_family = AF_INET;
487 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
488 addr4->sin_port = netorder_port;
489 } else if (ip->size == 16) {
490 addr->len = sizeof(struct sockaddr_in6);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700491 struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&addr->addr;
David Garcia Quintas107ca162016-11-02 18:17:03 -0700492 addr6->sin6_family = AF_INET6;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100493 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
494 addr6->sin6_port = netorder_port;
495 }
496}
497
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700498/* Returns addresses extracted from \a serverlist. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700499static grpc_lb_addresses* process_serverlist_locked(
500 grpc_exec_ctx* exec_ctx, const grpc_grpclb_serverlist* serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700501 size_t num_valid = 0;
502 /* first pass: count how many are valid in order to allocate the necessary
503 * memory in a single block */
504 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700505 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700506 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700507 grpc_lb_addresses* lb_addresses =
Mark D. Roth16883a32016-10-21 10:30:58 -0700508 grpc_lb_addresses_create(num_valid, &lb_token_vtable);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700509 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700510 * to the outside world) to be read by the RR policy during its creation.
511 * Given that the validity tests are very cheap, they are performed again
512 * instead of marking the valid ones during the first pass, as this would
513 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700514 size_t addr_idx = 0;
515 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700516 const grpc_grpclb_server* server = serverlist->servers[sl_idx];
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700517 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintasc22c65b2017-07-25 14:22:20 -0700518 GPR_ASSERT(addr_idx < num_valid);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700519 /* address processing */
Mark D. Rothc5c38782016-09-16 08:51:01 -0700520 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100521 parse_server(server, &addr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700522 /* lb token processing */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700523 void* user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700524 if (server->has_load_balance_token) {
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200525 const size_t lb_token_max_length =
526 GPR_ARRAY_SIZE(server->load_balance_token);
527 const size_t lb_token_length =
528 strnlen(server->load_balance_token, lb_token_max_length);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800529 grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
530 server->load_balance_token, lb_token_length);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700531 user_data = (void*)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
532 lb_token_mdstr)
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800533 .payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700534 } else {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700535 char* uri = grpc_sockaddr_to_uri(&addr);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800536 gpr_log(GPR_INFO,
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700537 "Missing LB token for backend address '%s'. The empty token will "
538 "be used instead",
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800539 uri);
540 gpr_free(uri);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700541 user_data = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700542 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700543
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700544 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
545 false /* is_balancer */,
Craig Tiller4782d922017-11-10 09:53:21 -0800546 nullptr /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700547 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700548 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700549 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700550 return lb_addresses;
551}
552
Juanli Shenfe408152017-09-27 12:27:20 -0700553/* Returns the backend addresses extracted from the given addresses */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700554static grpc_lb_addresses* extract_backend_addresses_locked(
555 grpc_exec_ctx* exec_ctx, const grpc_lb_addresses* addresses) {
Juanli Shenfe408152017-09-27 12:27:20 -0700556 /* first pass: count the number of backend addresses */
557 size_t num_backends = 0;
558 for (size_t i = 0; i < addresses->num_addresses; ++i) {
559 if (!addresses->addresses[i].is_balancer) {
560 ++num_backends;
561 }
562 }
563 /* second pass: actually populate the addresses and (empty) LB tokens */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700564 grpc_lb_addresses* backend_addresses =
Juanli Shenfe408152017-09-27 12:27:20 -0700565 grpc_lb_addresses_create(num_backends, &lb_token_vtable);
566 size_t num_copied = 0;
567 for (size_t i = 0; i < addresses->num_addresses; ++i) {
568 if (addresses->addresses[i].is_balancer) continue;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700569 const grpc_resolved_address* addr = &addresses->addresses[i].address;
Juanli Shenfe408152017-09-27 12:27:20 -0700570 grpc_lb_addresses_set_address(backend_addresses, num_copied, &addr->addr,
571 addr->len, false /* is_balancer */,
Craig Tiller4ac2b8e2017-11-10 14:14:17 -0800572 nullptr /* balancer_name */,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700573 (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload);
Juanli Shenfe408152017-09-27 12:27:20 -0700574 ++num_copied;
575 }
576 return backend_addresses;
577}
578
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700579static void update_lb_connectivity_status_locked(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700580 grpc_exec_ctx* exec_ctx, glb_lb_policy* glb_policy,
581 grpc_connectivity_state rr_state, grpc_error* rr_state_error) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800582 const grpc_connectivity_state curr_glb_state =
583 grpc_connectivity_state_check(&glb_policy->state_tracker);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800584
585 /* The new connectivity status is a function of the previous one and the new
586 * input coming from the status of the RR policy.
587 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800588 * current state (grpclb's)
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800589 * |
590 * v || I | C | R | TF | SD | <- new state (RR's)
591 * ===++====+=====+=====+======+======+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800592 * I || I | C | R | [I] | [I] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800593 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800594 * C || I | C | R | [C] | [C] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800595 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800596 * R || I | C | R | [R] | [R] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800597 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800598 * TF || I | C | R | [TF] | [TF] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800599 * ---++----+-----+-----+------+------+
600 * SD || NA | NA | NA | NA | NA | (*)
601 * ---++----+-----+-----+------+------+
602 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800603 * A [STATE] indicates that the old RR policy is kept. In those cases, STATE
604 * is the current state of grpclb, which is left untouched.
605 *
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800606 * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
607 * the previous RR instance.
608 *
609 * Note that the status is never updated to SHUTDOWN as a result of calling
610 * this function. Only glb_shutdown() has the power to set that state.
611 *
612 * (*) This function mustn't be called during shutting down. */
613 GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
614
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700615 switch (rr_state) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800616 case GRPC_CHANNEL_TRANSIENT_FAILURE:
617 case GRPC_CHANNEL_SHUTDOWN:
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700618 GPR_ASSERT(rr_state_error != GRPC_ERROR_NONE);
619 break;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800620 case GRPC_CHANNEL_IDLE:
621 case GRPC_CHANNEL_CONNECTING:
622 case GRPC_CHANNEL_READY:
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700623 GPR_ASSERT(rr_state_error == GRPC_ERROR_NONE);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800624 }
625
Craig Tiller84f75d42017-05-03 13:06:35 -0700626 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700627 gpr_log(
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800628 GPR_INFO,
629 "[grpclb %p] Setting grpclb's state to %s from new RR policy %p state.",
630 glb_policy, grpc_connectivity_state_name(rr_state),
631 glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800632 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700633 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, rr_state,
David Garcia Quintasc22c65b2017-07-25 14:22:20 -0700634 rr_state_error,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800635 "update_lb_connectivity_status_locked");
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800636}
637
Mark D. Rothd7389b42017-05-17 12:22:17 -0700638/* Perform a pick over \a glb_policy->rr_policy. Given that a pick can return
639 * immediately (ignoring its completion callback), we need to perform the
640 * cleanups this callback would otherwise be resposible for.
641 * If \a force_async is true, then we will manually schedule the
642 * completion callback even if the pick is available immediately. */
David Garcia Quintas20359062016-10-15 15:22:51 -0700643static bool pick_from_internal_rr_locked(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700644 grpc_exec_ctx* exec_ctx, glb_lb_policy* glb_policy,
645 const grpc_lb_policy_pick_args* pick_args, bool force_async,
646 grpc_connected_subchannel** target, wrapped_rr_closure_arg* wc_arg) {
Juanli Shenfe408152017-09-27 12:27:20 -0700647 // Check for drops if we are not using fallback backend addresses.
Craig Tiller4782d922017-11-10 09:53:21 -0800648 if (glb_policy->serverlist != nullptr) {
Juanli Shenfe408152017-09-27 12:27:20 -0700649 // Look at the index into the serverlist to see if we should drop this call.
Craig Tillerbaa14a92017-11-03 09:09:36 -0700650 grpc_grpclb_server* server =
Juanli Shenfe408152017-09-27 12:27:20 -0700651 glb_policy->serverlist->servers[glb_policy->serverlist_index++];
652 if (glb_policy->serverlist_index == glb_policy->serverlist->num_servers) {
653 glb_policy->serverlist_index = 0; // Wrap-around.
Mark D. Rothd7389b42017-05-17 12:22:17 -0700654 }
Juanli Shenfe408152017-09-27 12:27:20 -0700655 if (server->drop) {
656 // Not using the RR policy, so unref it.
657 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800658 gpr_log(GPR_INFO, "[grpclb %p] Unreffing RR %p for drop", glb_policy,
David Garcia Quintas2b372e02017-11-09 14:15:59 -0800659 wc_arg->rr_policy);
Juanli Shenfe408152017-09-27 12:27:20 -0700660 }
661 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
662 // Update client load reporting stats to indicate the number of
663 // dropped calls. Note that we have to do this here instead of in
664 // the client_load_reporting filter, because we do not create a
665 // subchannel call (and therefore no client_load_reporting filter)
666 // for dropped calls.
Craig Tiller6d0ec6b2017-11-10 14:20:46 -0800667 GPR_ASSERT(wc_arg->client_stats != nullptr);
Juanli Shenfe408152017-09-27 12:27:20 -0700668 grpc_grpclb_client_stats_add_call_dropped_locked(
669 server->load_balance_token, wc_arg->client_stats);
670 grpc_grpclb_client_stats_unref(wc_arg->client_stats);
671 if (force_async) {
Craig Tiller4782d922017-11-10 09:53:21 -0800672 GPR_ASSERT(wc_arg->wrapped_closure != nullptr);
Juanli Shenfe408152017-09-27 12:27:20 -0700673 GRPC_CLOSURE_SCHED(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
674 gpr_free(wc_arg->free_when_done);
675 return false;
676 }
Mark D. Rothd7389b42017-05-17 12:22:17 -0700677 gpr_free(wc_arg->free_when_done);
Juanli Shenfe408152017-09-27 12:27:20 -0700678 return true;
Mark D. Rothd7389b42017-05-17 12:22:17 -0700679 }
Mark D. Rothd7389b42017-05-17 12:22:17 -0700680 }
681 // Pick via the RR policy.
Craig Tiller2400bf52017-02-09 16:25:19 -0800682 const bool pick_done = grpc_lb_policy_pick_locked(
Mark D. Rothd7389b42017-05-17 12:22:17 -0700683 exec_ctx, wc_arg->rr_policy, pick_args, target, wc_arg->context,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700684 (void**)&wc_arg->lb_token, &wc_arg->wrapper_closure);
David Garcia Quintas20359062016-10-15 15:22:51 -0700685 if (pick_done) {
686 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
Craig Tiller84f75d42017-05-03 13:06:35 -0700687 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800688 gpr_log(GPR_INFO, "[grpclb %p] Unreffing RR %p", glb_policy,
689 wc_arg->rr_policy);
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700690 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200691 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
David Garcia Quintas20359062016-10-15 15:22:51 -0700692 /* add the load reporting initial metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800693 initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
David Garcia Quintas20359062016-10-15 15:22:51 -0700694 pick_args->lb_token_mdelem_storage,
695 GRPC_MDELEM_REF(wc_arg->lb_token));
Mark D. Roth09e458c2017-05-02 08:13:26 -0700696 // Pass on client stats via context. Passes ownership of the reference.
Craig Tiller4782d922017-11-10 09:53:21 -0800697 GPR_ASSERT(wc_arg->client_stats != nullptr);
Mark D. Roth09e458c2017-05-02 08:13:26 -0700698 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
699 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
Mark D. Rothd7389b42017-05-17 12:22:17 -0700700 if (force_async) {
Craig Tiller4782d922017-11-10 09:53:21 -0800701 GPR_ASSERT(wc_arg->wrapped_closure != nullptr);
ncteisen969b46e2017-06-08 14:57:11 -0700702 GRPC_CLOSURE_SCHED(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
Mark D. Rothd7389b42017-05-17 12:22:17 -0700703 gpr_free(wc_arg->free_when_done);
704 return false;
705 }
Mark D. Roth09e458c2017-05-02 08:13:26 -0700706 gpr_free(wc_arg->free_when_done);
David Garcia Quintas20359062016-10-15 15:22:51 -0700707 }
708 /* else, the pending pick will be registered and taken care of by the
709 * pending pick list inside the RR policy (glb_policy->rr_policy).
710 * Eventually, wrapped_on_complete will be called, which will -among other
711 * things- add the LB token to the call's initial metadata */
David Garcia Quintas20359062016-10-15 15:22:51 -0700712 return pick_done;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700713}
714
Craig Tillerbaa14a92017-11-03 09:09:36 -0700715static grpc_lb_policy_args* lb_policy_args_create(grpc_exec_ctx* exec_ctx,
716 glb_lb_policy* glb_policy) {
717 grpc_lb_addresses* addresses;
Craig Tiller4782d922017-11-10 09:53:21 -0800718 if (glb_policy->serverlist != nullptr) {
Juanli Shenfe408152017-09-27 12:27:20 -0700719 GPR_ASSERT(glb_policy->serverlist->num_servers > 0);
720 addresses = process_serverlist_locked(exec_ctx, glb_policy->serverlist);
721 } else {
722 // If rr_handover_locked() is invoked when we haven't received any
723 // serverlist from the balancer, we use the fallback backends returned by
724 // the resolver. Note that the fallback backend list may be empty, in which
725 // case the new round_robin policy will keep the requested picks pending.
Craig Tiller4782d922017-11-10 09:53:21 -0800726 GPR_ASSERT(glb_policy->fallback_backend_addresses != nullptr);
Juanli Shenfe408152017-09-27 12:27:20 -0700727 addresses = grpc_lb_addresses_copy(glb_policy->fallback_backend_addresses);
728 }
Craig Tiller4782d922017-11-10 09:53:21 -0800729 GPR_ASSERT(addresses != nullptr);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700730 grpc_lb_policy_args* args = (grpc_lb_policy_args*)gpr_zalloc(sizeof(*args));
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700731 args->client_channel_factory = glb_policy->cc_factory;
732 args->combiner = glb_policy->base.combiner;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700733 // Replace the LB addresses in the channel args that we pass down to
734 // the subchannel.
Craig Tillerbaa14a92017-11-03 09:09:36 -0700735 static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200736 const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700737 args->args = grpc_channel_args_copy_and_add_and_remove(
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700738 glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
739 1);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800740 grpc_lb_addresses_destroy(exec_ctx, addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700741 return args;
742}
743
Craig Tillerbaa14a92017-11-03 09:09:36 -0700744static void lb_policy_args_destroy(grpc_exec_ctx* exec_ctx,
745 grpc_lb_policy_args* args) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700746 grpc_channel_args_destroy(exec_ctx, args->args);
747 gpr_free(args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700748}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700749
Craig Tillerbaa14a92017-11-03 09:09:36 -0700750static void glb_rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx,
751 void* arg, grpc_error* error);
752static void create_rr_locked(grpc_exec_ctx* exec_ctx, glb_lb_policy* glb_policy,
753 grpc_lb_policy_args* args) {
Craig Tiller4782d922017-11-10 09:53:21 -0800754 GPR_ASSERT(glb_policy->rr_policy == nullptr);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800755
Craig Tillerbaa14a92017-11-03 09:09:36 -0700756 grpc_lb_policy* new_rr_policy =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700757 grpc_lb_policy_create(exec_ctx, "round_robin", args);
Craig Tiller4782d922017-11-10 09:53:21 -0800758 if (new_rr_policy == nullptr) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800759 gpr_log(GPR_ERROR,
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800760 "[grpclb %p] Failure creating a RoundRobin policy for serverlist "
David Garcia Quintas2b372e02017-11-09 14:15:59 -0800761 "update with %" PRIuPTR
762 " entries. The previous RR instance (%p), if any, will continue to "
763 "be used. Future updates from the LB will attempt to create new "
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800764 "instances.",
David Garcia Quintas2b372e02017-11-09 14:15:59 -0800765 glb_policy, glb_policy->serverlist->num_servers,
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800766 glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800767 return;
David Garcia Quintas65318262016-07-29 13:43:38 -0700768 }
David Garcia Quintas4283a262016-11-18 10:43:56 -0800769 glb_policy->rr_policy = new_rr_policy;
Craig Tiller4782d922017-11-10 09:53:21 -0800770 grpc_error* rr_state_error = nullptr;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700771 const grpc_connectivity_state rr_state =
772 grpc_lb_policy_check_connectivity_locked(exec_ctx, glb_policy->rr_policy,
773 &rr_state_error);
774 /* Connectivity state is a function of the RR policy updated/created */
775 update_lb_connectivity_status_locked(exec_ctx, glb_policy, rr_state,
776 rr_state_error);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800777 /* Add the gRPC LB's interested_parties pollset_set to that of the newly
778 * created RR policy. This will make the RR policy progress upon activity on
779 * gRPC LB, which in turn is tied to the application's call */
Yuchen Zengb4291642016-09-01 19:17:14 -0700780 grpc_pollset_set_add_pollset_set(exec_ctx,
781 glb_policy->rr_policy->interested_parties,
782 glb_policy->base.interested_parties);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200783
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800784 /* Allocate the data for the tracking of the new RR policy's connectivity.
785 * It'll be deallocated in glb_rr_connectivity_changed() */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700786 rr_connectivity_data* rr_connectivity =
787 (rr_connectivity_data*)gpr_zalloc(sizeof(rr_connectivity_data));
ncteisen969b46e2017-06-08 14:57:11 -0700788 GRPC_CLOSURE_INIT(&rr_connectivity->on_change,
Craig Tiller2400bf52017-02-09 16:25:19 -0800789 glb_rr_connectivity_changed_locked, rr_connectivity,
Craig Tilleree4b1452017-05-12 10:56:03 -0700790 grpc_combiner_scheduler(glb_policy->base.combiner));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200791 rr_connectivity->glb_policy = glb_policy;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700792 rr_connectivity->state = rr_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200793
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800794 /* Subscribe to changes to the connectivity of the new RR */
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700795 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "glb_rr_connectivity_cb");
Craig Tiller2400bf52017-02-09 16:25:19 -0800796 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
797 &rr_connectivity->state,
798 &rr_connectivity->on_change);
799 grpc_lb_policy_exit_idle_locked(exec_ctx, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700800
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800801 /* Update picks and pings in wait */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700802 pending_pick* pp;
David Garcia Quintas65318262016-07-29 13:43:38 -0700803 while ((pp = glb_policy->pending_picks)) {
804 glb_policy->pending_picks = pp->next;
805 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
806 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700807 pp->wrapped_on_complete_arg.client_stats =
808 grpc_grpclb_client_stats_ref(glb_policy->client_stats);
Craig Tiller84f75d42017-05-03 13:06:35 -0700809 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800810 gpr_log(GPR_INFO,
811 "[grpclb %p] Pending pick about to (async) PICK from RR %p",
812 glb_policy, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700813 }
Mark D. Rothd7389b42017-05-17 12:22:17 -0700814 pick_from_internal_rr_locked(exec_ctx, glb_policy, &pp->pick_args,
815 true /* force_async */, pp->target,
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700816 &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700817 }
818
Craig Tillerbaa14a92017-11-03 09:09:36 -0700819 pending_ping* pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700820 while ((pping = glb_policy->pending_pings)) {
821 glb_policy->pending_pings = pping->next;
822 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
823 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
Craig Tiller84f75d42017-05-03 13:06:35 -0700824 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800825 gpr_log(GPR_INFO, "[grpclb %p] Pending ping about to PING from RR %p",
826 glb_policy, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700827 }
Craig Tiller2400bf52017-02-09 16:25:19 -0800828 grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy,
829 &pping->wrapped_notify_arg.wrapper_closure);
David Garcia Quintas65318262016-07-29 13:43:38 -0700830 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700831}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700832
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700833/* glb_policy->rr_policy may be NULL (initial handover) */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700834static void rr_handover_locked(grpc_exec_ctx* exec_ctx,
835 glb_lb_policy* glb_policy) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700836 if (glb_policy->shutting_down) return;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700837 grpc_lb_policy_args* args = lb_policy_args_create(exec_ctx, glb_policy);
Craig Tiller4782d922017-11-10 09:53:21 -0800838 GPR_ASSERT(args != nullptr);
839 if (glb_policy->rr_policy != nullptr) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700840 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800841 gpr_log(GPR_DEBUG, "[grpclb %p] Updating RR policy %p", glb_policy,
842 glb_policy->rr_policy);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700843 }
844 grpc_lb_policy_update_locked(exec_ctx, glb_policy->rr_policy, args);
845 } else {
846 create_rr_locked(exec_ctx, glb_policy, args);
847 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800848 gpr_log(GPR_DEBUG, "[grpclb %p] Created new RR policy %p", glb_policy,
849 glb_policy->rr_policy);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700850 }
851 }
852 lb_policy_args_destroy(exec_ctx, args);
853}
854
Craig Tillerbaa14a92017-11-03 09:09:36 -0700855static void glb_rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx,
856 void* arg, grpc_error* error) {
857 rr_connectivity_data* rr_connectivity = (rr_connectivity_data*)arg;
858 glb_lb_policy* glb_policy = rr_connectivity->glb_policy;
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700859 if (glb_policy->shutting_down) {
David Garcia Quintas4283a262016-11-18 10:43:56 -0800860 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700861 "glb_rr_connectivity_cb");
862 gpr_free(rr_connectivity);
863 return;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800864 }
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700865 if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN) {
866 /* An RR policy that has transitioned into the SHUTDOWN connectivity state
867 * should not be considered for picks or updates: the SHUTDOWN state is a
868 * sink, policies can't transition back from it. .*/
869 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy,
870 "rr_connectivity_shutdown");
Craig Tiller4782d922017-11-10 09:53:21 -0800871 glb_policy->rr_policy = nullptr;
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700872 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
873 "glb_rr_connectivity_cb");
874 gpr_free(rr_connectivity);
875 return;
876 }
877 /* rr state != SHUTDOWN && !glb_policy->shutting down: biz as usual */
878 update_lb_connectivity_status_locked(
879 exec_ctx, glb_policy, rr_connectivity->state, GRPC_ERROR_REF(error));
880 /* Resubscribe. Reuse the "glb_rr_connectivity_cb" weak ref. */
881 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
882 &rr_connectivity->state,
883 &rr_connectivity->on_change);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700884}
885
Craig Tillerbaa14a92017-11-03 09:09:36 -0700886static void destroy_balancer_name(grpc_exec_ctx* exec_ctx,
887 void* balancer_name) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800888 gpr_free(balancer_name);
889}
890
David Garcia Quintas01291502017-02-07 13:26:41 -0800891static grpc_slice_hash_table_entry targets_info_entry_create(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700892 const char* address, const char* balancer_name) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800893 grpc_slice_hash_table_entry entry;
894 entry.key = grpc_slice_from_copied_string(address);
Mark D. Rothe3006702017-04-19 07:43:56 -0700895 entry.value = gpr_strdup(balancer_name);
David Garcia Quintas01291502017-02-07 13:26:41 -0800896 return entry;
897}
898
Craig Tillerbaa14a92017-11-03 09:09:36 -0700899static int balancer_name_cmp_fn(void* a, void* b) {
900 const char* a_str = (const char*)a;
901 const char* b_str = (const char*)b;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700902 return strcmp(a_str, b_str);
903}
904
905/* Returns the channel args for the LB channel, used to create a bidirectional
906 * stream for the reception of load balancing updates.
David Garcia Quintas01291502017-02-07 13:26:41 -0800907 *
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700908 * Inputs:
909 * - \a addresses: corresponding to the balancers.
910 * - \a response_generator: in order to propagate updates from the resolver
911 * above the grpclb policy.
912 * - \a args: other args inherited from the grpclb policy. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700913static grpc_channel_args* build_lb_channel_args(
914 grpc_exec_ctx* exec_ctx, const grpc_lb_addresses* addresses,
915 grpc_fake_resolver_response_generator* response_generator,
916 const grpc_channel_args* args) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800917 size_t num_grpclb_addrs = 0;
918 for (size_t i = 0; i < addresses->num_addresses; ++i) {
919 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
920 }
921 /* All input addresses come from a resolver that claims they are LB services.
922 * It's the resolver's responsibility to make sure this policy is only
923 * instantiated and used in that case. Otherwise, something has gone wrong. */
924 GPR_ASSERT(num_grpclb_addrs > 0);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700925 grpc_lb_addresses* lb_addresses =
Craig Tiller4782d922017-11-10 09:53:21 -0800926 grpc_lb_addresses_create(num_grpclb_addrs, nullptr);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700927 grpc_slice_hash_table_entry* targets_info_entries =
928 (grpc_slice_hash_table_entry*)gpr_zalloc(sizeof(*targets_info_entries) *
929 num_grpclb_addrs);
David Garcia Quintas01291502017-02-07 13:26:41 -0800930
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700931 size_t lb_addresses_idx = 0;
932 for (size_t i = 0; i < addresses->num_addresses; ++i) {
933 if (!addresses->addresses[i].is_balancer) continue;
Craig Tiller4782d922017-11-10 09:53:21 -0800934 if (addresses->addresses[i].user_data != nullptr) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800935 gpr_log(GPR_ERROR,
936 "This LB policy doesn't support user data. It will be ignored");
937 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700938 char* addr_str;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700939 GPR_ASSERT(grpc_sockaddr_to_string(
940 &addr_str, &addresses->addresses[i].address, true) > 0);
941 targets_info_entries[lb_addresses_idx] = targets_info_entry_create(
942 addr_str, addresses->addresses[i].balancer_name);
943 gpr_free(addr_str);
944
945 grpc_lb_addresses_set_address(
946 lb_addresses, lb_addresses_idx++, addresses->addresses[i].address.addr,
947 addresses->addresses[i].address.len, false /* is balancer */,
Craig Tiller4782d922017-11-10 09:53:21 -0800948 addresses->addresses[i].balancer_name, nullptr /* user data */);
David Garcia Quintas01291502017-02-07 13:26:41 -0800949 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700950 GPR_ASSERT(num_grpclb_addrs == lb_addresses_idx);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700951 grpc_slice_hash_table* targets_info =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700952 grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries,
953 destroy_balancer_name, balancer_name_cmp_fn);
David Garcia Quintas01291502017-02-07 13:26:41 -0800954 gpr_free(targets_info_entries);
955
Craig Tillerbaa14a92017-11-03 09:09:36 -0700956 grpc_channel_args* lb_channel_args =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700957 grpc_lb_policy_grpclb_build_lb_channel_args(exec_ctx, targets_info,
958 response_generator, args);
959
960 grpc_arg lb_channel_addresses_arg =
961 grpc_lb_addresses_create_channel_arg(lb_addresses);
962
Craig Tillerbaa14a92017-11-03 09:09:36 -0700963 grpc_channel_args* result = grpc_channel_args_copy_and_add(
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700964 lb_channel_args, &lb_channel_addresses_arg, 1);
965 grpc_slice_hash_table_unref(exec_ctx, targets_info);
966 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
967 grpc_lb_addresses_destroy(exec_ctx, lb_addresses);
968 return result;
David Garcia Quintas01291502017-02-07 13:26:41 -0800969}
970
Craig Tillerbaa14a92017-11-03 09:09:36 -0700971static void glb_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
972 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
Craig Tiller4782d922017-11-10 09:53:21 -0800973 GPR_ASSERT(glb_policy->pending_picks == nullptr);
974 GPR_ASSERT(glb_policy->pending_pings == nullptr);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700975 gpr_free((void*)glb_policy->server_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800976 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
Craig Tiller4782d922017-11-10 09:53:21 -0800977 if (glb_policy->client_stats != nullptr) {
Mark D. Roth09e458c2017-05-02 08:13:26 -0700978 grpc_grpclb_client_stats_unref(glb_policy->client_stats);
979 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700980 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
Craig Tiller4782d922017-11-10 09:53:21 -0800981 if (glb_policy->serverlist != nullptr) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700982 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
983 }
Craig Tiller4782d922017-11-10 09:53:21 -0800984 if (glb_policy->fallback_backend_addresses != nullptr) {
Juanli Shenfe408152017-09-27 12:27:20 -0700985 grpc_lb_addresses_destroy(exec_ctx, glb_policy->fallback_backend_addresses);
986 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700987 grpc_fake_resolver_response_generator_unref(glb_policy->response_generator);
Juanli Shen6502ecc2017-09-13 13:10:54 -0700988 grpc_subchannel_index_unref();
David Garcia Quintas65318262016-07-29 13:43:38 -0700989 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700990}
991
Craig Tillerbaa14a92017-11-03 09:09:36 -0700992static void glb_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
993 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200994 glb_policy->shutting_down = true;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700995
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800996 /* We need a copy of the lb_call pointer because we can't cancell the call
997 * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
998 * the cancel, needs to acquire that same lock */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700999 grpc_call* lb_call = glb_policy->lb_call;
David Garcia Quintas65318262016-07-29 13:43:38 -07001000
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001001 /* glb_policy->lb_call and this local lb_call must be consistent at this point
1002 * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
1003 * of query_for_backends_locked, which can only be invoked while
1004 * glb_policy->shutting_down is false. */
Craig Tiller4782d922017-11-10 09:53:21 -08001005 if (lb_call != nullptr) {
1006 grpc_call_cancel(lb_call, nullptr);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001007 /* lb_on_server_status_received will pick up the cancel and clean up */
1008 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001009 if (glb_policy->retry_timer_active) {
1010 grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
1011 glb_policy->retry_timer_active = false;
1012 }
Juanli Shen663f50c2017-10-05 14:36:13 -07001013 if (glb_policy->fallback_timer_active) {
1014 grpc_timer_cancel(exec_ctx, &glb_policy->lb_fallback_timer);
1015 glb_policy->fallback_timer_active = false;
1016 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001017
Craig Tillerbaa14a92017-11-03 09:09:36 -07001018 pending_pick* pp = glb_policy->pending_picks;
Craig Tiller4782d922017-11-10 09:53:21 -08001019 glb_policy->pending_picks = nullptr;
Craig Tillerbaa14a92017-11-03 09:09:36 -07001020 pending_ping* pping = glb_policy->pending_pings;
Craig Tiller4782d922017-11-10 09:53:21 -08001021 glb_policy->pending_pings = nullptr;
1022 if (glb_policy->rr_policy != nullptr) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001023 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
1024 }
1025 // We destroy the LB channel here because
1026 // glb_lb_channel_on_connectivity_changed_cb needs a valid glb_policy
1027 // instance. Destroying the lb channel in glb_destroy would likely result in
1028 // a callback invocation without a valid glb_policy arg.
Craig Tiller4782d922017-11-10 09:53:21 -08001029 if (glb_policy->lb_channel != nullptr) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001030 grpc_channel_destroy(glb_policy->lb_channel);
Craig Tiller4782d922017-11-10 09:53:21 -08001031 glb_policy->lb_channel = nullptr;
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001032 }
1033 grpc_connectivity_state_set(
1034 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
1035 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "glb_shutdown");
1036
Craig Tiller4782d922017-11-10 09:53:21 -08001037 while (pp != nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001038 pending_pick* next = pp->next;
Craig Tiller4782d922017-11-10 09:53:21 -08001039 *pp->target = nullptr;
Mark D. Roth8ba4bf42017-10-05 13:16:33 -07001040 GRPC_CLOSURE_SCHED(
1041 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
1042 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"));
Mark D. Roth7a2db962017-10-06 15:06:12 -07001043 gpr_free(pp);
David Garcia Quintas65318262016-07-29 13:43:38 -07001044 pp = next;
1045 }
1046
Craig Tiller4782d922017-11-10 09:53:21 -08001047 while (pping != nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001048 pending_ping* next = pping->next;
Mark D. Roth8ba4bf42017-10-05 13:16:33 -07001049 GRPC_CLOSURE_SCHED(
1050 exec_ctx, &pping->wrapped_notify_arg.wrapper_closure,
1051 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"));
Mark D. Roth7a2db962017-10-06 15:06:12 -07001052 gpr_free(pping);
David Garcia Quintas65318262016-07-29 13:43:38 -07001053 pping = next;
1054 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001055}
1056
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001057// Cancel a specific pending pick.
1058//
1059// A grpclb pick progresses as follows:
1060// - If there's a Round Robin policy (glb_policy->rr_policy) available, it'll be
1061// handed over to the RR policy (in create_rr_locked()). From that point
1062// onwards, it'll be RR's responsibility. For cancellations, that implies the
1063// pick needs also be cancelled by the RR instance.
1064// - Otherwise, without an RR instance, picks stay pending at this policy's
1065// level (grpclb), inside the glb_policy->pending_picks list. To cancel these,
1066// we invoke the completion closure and set *target to NULL right here.
Craig Tillerbaa14a92017-11-03 09:09:36 -07001067static void glb_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1068 grpc_connected_subchannel** target,
1069 grpc_error* error) {
1070 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
1071 pending_pick* pp = glb_policy->pending_picks;
Craig Tiller4782d922017-11-10 09:53:21 -08001072 glb_policy->pending_picks = nullptr;
1073 while (pp != nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001074 pending_pick* next = pp->next;
David Garcia Quintas65318262016-07-29 13:43:38 -07001075 if (pp->target == target) {
Craig Tiller4782d922017-11-10 09:53:21 -08001076 *target = nullptr;
ncteisen969b46e2017-06-08 14:57:11 -07001077 GRPC_CLOSURE_SCHED(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
ncteisen4b36a3d2017-03-13 19:08:06 -07001078 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1079 "Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -07001080 } else {
1081 pp->next = glb_policy->pending_picks;
1082 glb_policy->pending_picks = pp;
1083 }
1084 pp = next;
1085 }
Craig Tiller4782d922017-11-10 09:53:21 -08001086 if (glb_policy->rr_policy != nullptr) {
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001087 grpc_lb_policy_cancel_pick_locked(exec_ctx, glb_policy->rr_policy, target,
1088 GRPC_ERROR_REF(error));
1089 }
Mark D. Roth5f844002016-09-08 08:20:53 -07001090 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001091}
1092
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001093// Cancel all pending picks.
1094//
1095// A grpclb pick progresses as follows:
1096// - If there's a Round Robin policy (glb_policy->rr_policy) available, it'll be
1097// handed over to the RR policy (in create_rr_locked()). From that point
1098// onwards, it'll be RR's responsibility. For cancellations, that implies the
1099// pick needs also be cancelled by the RR instance.
1100// - Otherwise, without an RR instance, picks stay pending at this policy's
1101// level (grpclb), inside the glb_policy->pending_picks list. To cancel these,
1102// we invoke the completion closure and set *target to NULL right here.
Craig Tillerbaa14a92017-11-03 09:09:36 -07001103static void glb_cancel_picks_locked(grpc_exec_ctx* exec_ctx,
1104 grpc_lb_policy* pol,
Craig Tiller2400bf52017-02-09 16:25:19 -08001105 uint32_t initial_metadata_flags_mask,
1106 uint32_t initial_metadata_flags_eq,
Craig Tillerbaa14a92017-11-03 09:09:36 -07001107 grpc_error* error) {
1108 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
1109 pending_pick* pp = glb_policy->pending_picks;
Craig Tiller4782d922017-11-10 09:53:21 -08001110 glb_policy->pending_picks = nullptr;
1111 while (pp != nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001112 pending_pick* next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001113 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -07001114 initial_metadata_flags_eq) {
ncteisen969b46e2017-06-08 14:57:11 -07001115 GRPC_CLOSURE_SCHED(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
ncteisen4b36a3d2017-03-13 19:08:06 -07001116 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1117 "Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -07001118 } else {
1119 pp->next = glb_policy->pending_picks;
1120 glb_policy->pending_picks = pp;
1121 }
1122 pp = next;
1123 }
Craig Tiller4782d922017-11-10 09:53:21 -08001124 if (glb_policy->rr_policy != nullptr) {
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001125 grpc_lb_policy_cancel_picks_locked(
1126 exec_ctx, glb_policy->rr_policy, initial_metadata_flags_mask,
1127 initial_metadata_flags_eq, GRPC_ERROR_REF(error));
1128 }
Mark D. Rothe65ff112016-09-09 13:48:38 -07001129 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001130}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001131
Craig Tillerbaa14a92017-11-03 09:09:36 -07001132static void lb_on_fallback_timer_locked(grpc_exec_ctx* exec_ctx, void* arg,
1133 grpc_error* error);
1134static void query_for_backends_locked(grpc_exec_ctx* exec_ctx,
1135 glb_lb_policy* glb_policy);
1136static void start_picking_locked(grpc_exec_ctx* exec_ctx,
1137 glb_lb_policy* glb_policy) {
Juanli Shenfe408152017-09-27 12:27:20 -07001138 /* start a timer to fall back */
1139 if (glb_policy->lb_fallback_timeout_ms > 0 &&
Craig Tiller4782d922017-11-10 09:53:21 -08001140 glb_policy->serverlist == nullptr && !glb_policy->fallback_timer_active) {
Craig Tiller1e868f02017-09-29 11:18:26 -07001141 grpc_millis deadline =
1142 grpc_exec_ctx_now(exec_ctx) + glb_policy->lb_fallback_timeout_ms;
Juanli Shenfe408152017-09-27 12:27:20 -07001143 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_fallback_timer");
1144 GRPC_CLOSURE_INIT(&glb_policy->lb_on_fallback, lb_on_fallback_timer_locked,
1145 glb_policy,
1146 grpc_combiner_scheduler(glb_policy->base.combiner));
1147 glb_policy->fallback_timer_active = true;
1148 grpc_timer_init(exec_ctx, &glb_policy->lb_fallback_timer, deadline,
Craig Tiller1e868f02017-09-29 11:18:26 -07001149 &glb_policy->lb_on_fallback);
Juanli Shenfe408152017-09-27 12:27:20 -07001150 }
1151
David Garcia Quintas65318262016-07-29 13:43:38 -07001152 glb_policy->started_picking = true;
Craig Tillerc0df1c02017-07-17 16:12:33 -07001153 grpc_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001154 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001155}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001156
Craig Tillerbaa14a92017-11-03 09:09:36 -07001157static void glb_exit_idle_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
1158 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001159 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001160 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001161 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001162}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001163
Craig Tillerbaa14a92017-11-03 09:09:36 -07001164static int glb_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1165 const grpc_lb_policy_pick_args* pick_args,
1166 grpc_connected_subchannel** target,
1167 grpc_call_context_element* context, void** user_data,
1168 grpc_closure* on_complete) {
Craig Tiller4782d922017-11-10 09:53:21 -08001169 if (pick_args->lb_token_mdelem_storage == nullptr) {
1170 *target = nullptr;
ncteisen969b46e2017-06-08 14:57:11 -07001171 GRPC_CLOSURE_SCHED(exec_ctx, on_complete,
ncteisen4b36a3d2017-03-13 19:08:06 -07001172 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1173 "No mdelem storage for the LB token. Load reporting "
1174 "won't work without it. Failing"));
Mark D. Roth1e5f6af2016-10-07 08:32:58 -07001175 return 0;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001176 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001177 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001178 bool pick_done = false;
Craig Tiller4782d922017-11-10 09:53:21 -08001179 if (glb_policy->rr_policy != nullptr) {
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001180 const grpc_connectivity_state rr_connectivity_state =
Craig Tillerbe98d242017-11-10 15:26:57 -08001181 grpc_lb_policy_check_connectivity_locked(
1182 exec_ctx, glb_policy->rr_policy, nullptr);
David Garcia Quintasf6c6b922017-11-03 07:48:16 -07001183 // The glb_policy->rr_policy may have transitioned to SHUTDOWN but the
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001184 // callback registered to capture this event
1185 // (glb_rr_connectivity_changed_locked) may not have been invoked yet. We
1186 // need to make sure we aren't trying to pick from a RR policy instance
1187 // that's in shutdown.
1188 if (rr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
1189 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
1190 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001191 "[grpclb %p] NOT picking from from RR %p: RR conn state=%s",
1192 glb_policy, glb_policy->rr_policy,
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001193 grpc_connectivity_state_name(rr_connectivity_state));
1194 }
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001195 add_pending_pick(&glb_policy->pending_picks, pick_args, target, context,
1196 on_complete);
1197 pick_done = false;
1198 } else { // RR not in shutdown
1199 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001200 gpr_log(GPR_INFO, "[grpclb %p] about to PICK from RR %p", glb_policy,
1201 glb_policy->rr_policy);
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001202 }
1203 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
Craig Tiller34992a62017-11-06 12:33:42 -08001204 wrapped_rr_closure_arg* wc_arg =
1205 (wrapped_rr_closure_arg*)gpr_zalloc(sizeof(wrapped_rr_closure_arg));
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001206 GRPC_CLOSURE_INIT(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
1207 grpc_schedule_on_exec_ctx);
1208 wc_arg->rr_policy = glb_policy->rr_policy;
1209 wc_arg->target = target;
1210 wc_arg->context = context;
Craig Tiller4782d922017-11-10 09:53:21 -08001211 GPR_ASSERT(glb_policy->client_stats != nullptr);
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001212 wc_arg->client_stats =
1213 grpc_grpclb_client_stats_ref(glb_policy->client_stats);
1214 wc_arg->wrapped_closure = on_complete;
1215 wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
1216 wc_arg->initial_metadata = pick_args->initial_metadata;
1217 wc_arg->free_when_done = wc_arg;
David Garcia Quintas6712a752017-11-10 12:09:25 -08001218 wc_arg->glb_policy = pol;
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001219 pick_done =
1220 pick_from_internal_rr_locked(exec_ctx, glb_policy, pick_args,
1221 false /* force_async */, target, wc_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -07001222 }
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001223 } else { // glb_policy->rr_policy == NULL
Craig Tiller84f75d42017-05-03 13:06:35 -07001224 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001225 gpr_log(GPR_DEBUG,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001226 "[grpclb %p] No RR policy. Adding to grpclb's pending picks",
1227 glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001228 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001229 add_pending_pick(&glb_policy->pending_picks, pick_args, target, context,
David Garcia Quintas8aace512016-08-15 14:55:12 -07001230 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -07001231 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001232 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001233 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001234 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001235 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001236 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001237}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001238
Craig Tiller2400bf52017-02-09 16:25:19 -08001239static grpc_connectivity_state glb_check_connectivity_locked(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001240 grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1241 grpc_error** connectivity_error) {
1242 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
Craig Tiller2400bf52017-02-09 16:25:19 -08001243 return grpc_connectivity_state_get(&glb_policy->state_tracker,
1244 connectivity_error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001245}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001246
Craig Tillerbaa14a92017-11-03 09:09:36 -07001247static void glb_ping_one_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1248 grpc_closure* closure) {
1249 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001250 if (glb_policy->rr_policy) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001251 grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, closure);
David Garcia Quintas65318262016-07-29 13:43:38 -07001252 } else {
1253 add_pending_ping(&glb_policy->pending_pings, closure);
1254 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001255 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001256 }
1257 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001258}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001259
Craig Tillerbaa14a92017-11-03 09:09:36 -07001260static void glb_notify_on_state_change_locked(grpc_exec_ctx* exec_ctx,
1261 grpc_lb_policy* pol,
1262 grpc_connectivity_state* current,
1263 grpc_closure* notify) {
1264 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001265 grpc_connectivity_state_notify_on_state_change(
1266 exec_ctx, &glb_policy->state_tracker, current, notify);
David Garcia Quintas65318262016-07-29 13:43:38 -07001267}
1268
Craig Tillerbaa14a92017-11-03 09:09:36 -07001269static void lb_call_on_retry_timer_locked(grpc_exec_ctx* exec_ctx, void* arg,
1270 grpc_error* error) {
1271 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Mark D. Rotha4792f52017-09-26 09:06:35 -07001272 glb_policy->retry_timer_active = false;
Craig Tiller6d0ec6b2017-11-10 14:20:46 -08001273 if (!glb_policy->shutting_down && glb_policy->lb_call == nullptr &&
David Garcia Quintasb90cb3f2017-11-09 13:58:00 -08001274 error == GRPC_ERROR_NONE) {
Mark D. Rotha4792f52017-09-26 09:06:35 -07001275 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas2b372e02017-11-09 14:15:59 -08001276 gpr_log(GPR_INFO, "[grpclb %p] Restarting call to LB server", glb_policy);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001277 }
Mark D. Rotha4792f52017-09-26 09:06:35 -07001278 query_for_backends_locked(exec_ctx, glb_policy);
1279 }
1280 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, "grpclb_retry_timer");
1281}
1282
Craig Tillerbaa14a92017-11-03 09:09:36 -07001283static void maybe_restart_lb_call(grpc_exec_ctx* exec_ctx,
1284 glb_lb_policy* glb_policy) {
Mark D. Rotha4792f52017-09-26 09:06:35 -07001285 if (glb_policy->started_picking && glb_policy->updating_lb_call) {
1286 if (glb_policy->retry_timer_active) {
1287 grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
1288 }
1289 if (!glb_policy->shutting_down) start_picking_locked(exec_ctx, glb_policy);
1290 glb_policy->updating_lb_call = false;
1291 } else if (!glb_policy->shutting_down) {
1292 /* if we aren't shutting down, restart the LB client call after some time */
Craig Tiller1e868f02017-09-29 11:18:26 -07001293 grpc_millis next_try =
David Garcia Quintaseca25f32017-11-02 14:52:54 -07001294 grpc_backoff_step(exec_ctx, &glb_policy->lb_call_backoff_state)
1295 .next_attempt_start_time;
Mark D. Rotha4792f52017-09-26 09:06:35 -07001296 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001297 gpr_log(GPR_DEBUG, "[grpclb %p] Connection to LB server lost...",
1298 glb_policy);
Craig Tiller1e868f02017-09-29 11:18:26 -07001299 grpc_millis timeout = next_try - grpc_exec_ctx_now(exec_ctx);
1300 if (timeout > 0) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001301 gpr_log(GPR_DEBUG,
1302 "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.",
1303 glb_policy, timeout);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001304 } else {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001305 gpr_log(GPR_DEBUG, "[grpclb %p] ... retry_timer_active immediately.",
1306 glb_policy);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001307 }
1308 }
1309 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
1310 GRPC_CLOSURE_INIT(&glb_policy->lb_on_call_retry,
1311 lb_call_on_retry_timer_locked, glb_policy,
1312 grpc_combiner_scheduler(glb_policy->base.combiner));
1313 glb_policy->retry_timer_active = true;
1314 grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
Craig Tiller1e868f02017-09-29 11:18:26 -07001315 &glb_policy->lb_on_call_retry);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001316 }
1317 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1318 "lb_on_server_status_received_locked");
1319}
1320
Craig Tillerbaa14a92017-11-03 09:09:36 -07001321static void send_client_load_report_locked(grpc_exec_ctx* exec_ctx, void* arg,
1322 grpc_error* error);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001323
Craig Tillerbaa14a92017-11-03 09:09:36 -07001324static void schedule_next_client_load_report(grpc_exec_ctx* exec_ctx,
1325 glb_lb_policy* glb_policy) {
Craig Tillerc0df1c02017-07-17 16:12:33 -07001326 const grpc_millis next_client_load_report_time =
1327 grpc_exec_ctx_now(exec_ctx) + glb_policy->client_stats_report_interval;
ncteisen969b46e2017-06-08 14:57:11 -07001328 GRPC_CLOSURE_INIT(&glb_policy->client_load_report_closure,
Mark D. Roth09e458c2017-05-02 08:13:26 -07001329 send_client_load_report_locked, glb_policy,
Craig Tilleree4b1452017-05-12 10:56:03 -07001330 grpc_combiner_scheduler(glb_policy->base.combiner));
Mark D. Roth09e458c2017-05-02 08:13:26 -07001331 grpc_timer_init(exec_ctx, &glb_policy->client_load_report_timer,
1332 next_client_load_report_time,
Craig Tillerc0df1c02017-07-17 16:12:33 -07001333 &glb_policy->client_load_report_closure);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001334}
1335
Craig Tillerbaa14a92017-11-03 09:09:36 -07001336static void client_load_report_done_locked(grpc_exec_ctx* exec_ctx, void* arg,
1337 grpc_error* error) {
1338 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001339 grpc_byte_buffer_destroy(glb_policy->client_load_report_payload);
Craig Tiller4782d922017-11-10 09:53:21 -08001340 glb_policy->client_load_report_payload = nullptr;
1341 if (error != GRPC_ERROR_NONE || glb_policy->lb_call == nullptr) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001342 glb_policy->client_load_report_timer_pending = false;
1343 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1344 "client_load_report");
Mark D. Roth6c8ee582017-11-16 08:35:25 -08001345 if (glb_policy->lb_call == nullptr) {
1346 maybe_restart_lb_call(exec_ctx, glb_policy);
1347 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001348 return;
1349 }
1350 schedule_next_client_load_report(exec_ctx, glb_policy);
1351}
1352
Craig Tillerbaa14a92017-11-03 09:09:36 -07001353static bool load_report_counters_are_zero(grpc_grpclb_request* request) {
1354 grpc_grpclb_dropped_call_counts* drop_entries =
1355 (grpc_grpclb_dropped_call_counts*)
Yash Tibrewalbc130da2017-09-12 22:44:08 -07001356 request->client_stats.calls_finished_with_drop.arg;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001357 return request->client_stats.num_calls_started == 0 &&
1358 request->client_stats.num_calls_finished == 0 &&
Mark D. Roth09e458c2017-05-02 08:13:26 -07001359 request->client_stats.num_calls_finished_with_client_failed_to_send ==
1360 0 &&
Mark D. Rothe7751802017-07-27 12:31:45 -07001361 request->client_stats.num_calls_finished_known_received == 0 &&
Craig Tiller4782d922017-11-10 09:53:21 -08001362 (drop_entries == nullptr || drop_entries->num_entries == 0);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001363}
1364
Craig Tillerbaa14a92017-11-03 09:09:36 -07001365static void send_client_load_report_locked(grpc_exec_ctx* exec_ctx, void* arg,
1366 grpc_error* error) {
1367 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Craig Tiller4782d922017-11-10 09:53:21 -08001368 if (error == GRPC_ERROR_CANCELLED || glb_policy->lb_call == nullptr) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001369 glb_policy->client_load_report_timer_pending = false;
1370 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1371 "client_load_report");
Craig Tiller4782d922017-11-10 09:53:21 -08001372 if (glb_policy->lb_call == nullptr) {
Mark D. Rotha4792f52017-09-26 09:06:35 -07001373 maybe_restart_lb_call(exec_ctx, glb_policy);
1374 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001375 return;
1376 }
1377 // Construct message payload.
Craig Tiller4782d922017-11-10 09:53:21 -08001378 GPR_ASSERT(glb_policy->client_load_report_payload == nullptr);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001379 grpc_grpclb_request* request =
Mark D. Rothe7751802017-07-27 12:31:45 -07001380 grpc_grpclb_load_report_request_create_locked(glb_policy->client_stats);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001381 // Skip client load report if the counters were all zero in the last
1382 // report and they are still zero in this one.
1383 if (load_report_counters_are_zero(request)) {
1384 if (glb_policy->last_client_load_report_counters_were_zero) {
1385 grpc_grpclb_request_destroy(request);
1386 schedule_next_client_load_report(exec_ctx, glb_policy);
1387 return;
1388 }
1389 glb_policy->last_client_load_report_counters_were_zero = true;
1390 } else {
1391 glb_policy->last_client_load_report_counters_were_zero = false;
1392 }
1393 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
1394 glb_policy->client_load_report_payload =
1395 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
1396 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
1397 grpc_grpclb_request_destroy(request);
Mark D. Roth2de36a82017-09-25 14:54:44 -07001398 // Send load report message.
1399 grpc_op op;
1400 memset(&op, 0, sizeof(op));
1401 op.op = GRPC_OP_SEND_MESSAGE;
1402 op.data.send_message.send_message = glb_policy->client_load_report_payload;
1403 GRPC_CLOSURE_INIT(&glb_policy->client_load_report_closure,
1404 client_load_report_done_locked, glb_policy,
1405 grpc_combiner_scheduler(glb_policy->base.combiner));
1406 grpc_call_error call_error = grpc_call_start_batch_and_execute(
1407 exec_ctx, glb_policy->lb_call, &op, 1,
1408 &glb_policy->client_load_report_closure);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001409 if (call_error != GRPC_CALL_OK) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001410 gpr_log(GPR_ERROR, "[grpclb %p] call_error=%d", glb_policy, call_error);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001411 GPR_ASSERT(GRPC_CALL_OK == call_error);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001412 }
1413}
1414
Craig Tillerbaa14a92017-11-03 09:09:36 -07001415static void lb_on_server_status_received_locked(grpc_exec_ctx* exec_ctx,
1416 void* arg, grpc_error* error);
1417static void lb_on_response_received_locked(grpc_exec_ctx* exec_ctx, void* arg,
1418 grpc_error* error);
1419static void lb_call_init_locked(grpc_exec_ctx* exec_ctx,
1420 glb_lb_policy* glb_policy) {
Craig Tiller4782d922017-11-10 09:53:21 -08001421 GPR_ASSERT(glb_policy->server_name != nullptr);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001422 GPR_ASSERT(glb_policy->server_name[0] != '\0');
Craig Tiller4782d922017-11-10 09:53:21 -08001423 GPR_ASSERT(glb_policy->lb_call == nullptr);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001424 GPR_ASSERT(!glb_policy->shutting_down);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001425
David Garcia Quintas15eba132016-08-09 15:20:48 -07001426 /* Note the following LB call progresses every time there's activity in \a
1427 * glb_policy->base.interested_parties, which is comprised of the polling
Yuchen Zengf7c45ae2016-09-15 13:40:32 -07001428 * entities from \a client_channel. */
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001429 grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
Craig Tiller89c14282017-07-19 15:32:27 -07001430 grpc_millis deadline =
Mark D. Roth64d922a2017-05-03 12:52:04 -07001431 glb_policy->lb_call_timeout_ms == 0
Craig Tiller89c14282017-07-19 15:32:27 -07001432 ? GRPC_MILLIS_INF_FUTURE
1433 : grpc_exec_ctx_now(exec_ctx) + glb_policy->lb_call_timeout_ms;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001434 glb_policy->lb_call = grpc_channel_create_pollset_set_call(
Craig Tiller4782d922017-11-10 09:53:21 -08001435 exec_ctx, glb_policy->lb_channel, nullptr, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -07001436 glb_policy->base.interested_parties,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001437 GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
Craig Tiller4782d922017-11-10 09:53:21 -08001438 &host, deadline, nullptr);
David Garcia Quintas7fadeae2017-04-18 14:38:56 -07001439 grpc_slice_unref_internal(exec_ctx, host);
David Garcia Quintas65318262016-07-29 13:43:38 -07001440
Craig Tiller4782d922017-11-10 09:53:21 -08001441 if (glb_policy->client_stats != nullptr) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001442 grpc_grpclb_client_stats_unref(glb_policy->client_stats);
1443 }
1444 glb_policy->client_stats = grpc_grpclb_client_stats_create();
1445
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001446 grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
1447 grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001448
Craig Tillerbaa14a92017-11-03 09:09:36 -07001449 grpc_grpclb_request* request =
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001450 grpc_grpclb_request_create(glb_policy->server_name);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001451 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001452 glb_policy->lb_request_payload =
David Garcia Quintas65318262016-07-29 13:43:38 -07001453 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001454 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
David Garcia Quintas65318262016-07-29 13:43:38 -07001455 grpc_grpclb_request_destroy(request);
1456
ncteisen969b46e2017-06-08 14:57:11 -07001457 GRPC_CLOSURE_INIT(&glb_policy->lb_on_server_status_received,
Craig Tiller2400bf52017-02-09 16:25:19 -08001458 lb_on_server_status_received_locked, glb_policy,
Craig Tilleree4b1452017-05-12 10:56:03 -07001459 grpc_combiner_scheduler(glb_policy->base.combiner));
ncteisen969b46e2017-06-08 14:57:11 -07001460 GRPC_CLOSURE_INIT(&glb_policy->lb_on_response_received,
Craig Tiller2400bf52017-02-09 16:25:19 -08001461 lb_on_response_received_locked, glb_policy,
Craig Tilleree4b1452017-05-12 10:56:03 -07001462 grpc_combiner_scheduler(glb_policy->base.combiner));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001463
Craig Tillerc0df1c02017-07-17 16:12:33 -07001464 grpc_backoff_init(&glb_policy->lb_call_backoff_state,
David Garcia Quintaseca25f32017-11-02 14:52:54 -07001465 GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
Craig Tillerc0df1c02017-07-17 16:12:33 -07001466 GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER,
1467 GRPC_GRPCLB_RECONNECT_JITTER,
1468 GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000,
1469 GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001470
Mark D. Roth09e458c2017-05-02 08:13:26 -07001471 glb_policy->seen_initial_response = false;
1472 glb_policy->last_client_load_report_counters_were_zero = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001473}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001474
Craig Tillerbaa14a92017-11-03 09:09:36 -07001475static void lb_call_destroy_locked(grpc_exec_ctx* exec_ctx,
1476 glb_lb_policy* glb_policy) {
Craig Tiller4782d922017-11-10 09:53:21 -08001477 GPR_ASSERT(glb_policy->lb_call != nullptr);
Craig Tillerdd36b152017-03-31 08:27:28 -07001478 grpc_call_unref(glb_policy->lb_call);
Craig Tiller4782d922017-11-10 09:53:21 -08001479 glb_policy->lb_call = nullptr;
David Garcia Quintas65318262016-07-29 13:43:38 -07001480
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001481 grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
1482 grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001483
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001484 grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001485 grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001486
Mark D. Roth9247ad52017-09-25 13:35:48 -07001487 if (glb_policy->client_load_report_timer_pending) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001488 grpc_timer_cancel(exec_ctx, &glb_policy->client_load_report_timer);
1489 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001490}
1491
David Garcia Quintas8d489112016-07-29 15:20:42 -07001492/*
1493 * Auxiliary functions and LB client callbacks.
1494 */
Craig Tillerbaa14a92017-11-03 09:09:36 -07001495static void query_for_backends_locked(grpc_exec_ctx* exec_ctx,
1496 glb_lb_policy* glb_policy) {
Craig Tiller4782d922017-11-10 09:53:21 -08001497 GPR_ASSERT(glb_policy->lb_channel != nullptr);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001498 if (glb_policy->shutting_down) return;
1499
Craig Tillerc5866662016-11-16 15:25:00 -08001500 lb_call_init_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001501
Craig Tiller84f75d42017-05-03 13:06:35 -07001502 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001503 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001504 "[grpclb %p] Query for backends (lb_channel: %p, lb_call: %p)",
1505 glb_policy, glb_policy->lb_channel, glb_policy->lb_call);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001506 }
Craig Tiller4782d922017-11-10 09:53:21 -08001507 GPR_ASSERT(glb_policy->lb_call != nullptr);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001508
David Garcia Quintas65318262016-07-29 13:43:38 -07001509 grpc_call_error call_error;
Mark D. Roth2de36a82017-09-25 14:54:44 -07001510 grpc_op ops[3];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001511 memset(ops, 0, sizeof(ops));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001512
Craig Tillerbaa14a92017-11-03 09:09:36 -07001513 grpc_op* op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -07001514 op->op = GRPC_OP_SEND_INITIAL_METADATA;
1515 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001516 op->flags = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001517 op->reserved = nullptr;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001518 op++;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001519 op->op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001520 op->data.recv_initial_metadata.recv_initial_metadata =
1521 &glb_policy->lb_initial_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001522 op->flags = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001523 op->reserved = nullptr;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001524 op++;
Craig Tiller4782d922017-11-10 09:53:21 -08001525 GPR_ASSERT(glb_policy->lb_request_payload != nullptr);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001526 op->op = GRPC_OP_SEND_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001527 op->data.send_message.send_message = glb_policy->lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001528 op->flags = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001529 op->reserved = nullptr;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001530 op++;
Craig Tillerbe98d242017-11-10 15:26:57 -08001531 call_error = grpc_call_start_batch_and_execute(
1532 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops), nullptr);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001533 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001534
Mark D. Roth09e458c2017-05-02 08:13:26 -07001535 op = ops;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001536 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1537 op->data.recv_status_on_client.trailing_metadata =
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001538 &glb_policy->lb_trailing_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001539 op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
1540 op->data.recv_status_on_client.status_details =
1541 &glb_policy->lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001542 op->flags = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001543 op->reserved = nullptr;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001544 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001545 /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001546 * count goes to zero) to be unref'd in lb_on_server_status_received_locked */
1547 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base,
1548 "lb_on_server_status_received_locked");
David Garcia Quintas65318262016-07-29 13:43:38 -07001549 call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001550 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1551 &glb_policy->lb_on_server_status_received);
David Garcia Quintas65318262016-07-29 13:43:38 -07001552 GPR_ASSERT(GRPC_CALL_OK == call_error);
1553
1554 op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001555 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001556 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001557 op->flags = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001558 op->reserved = nullptr;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001559 op++;
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001560 /* take another weak ref to be unref'd/reused in
1561 * lb_on_response_received_locked */
1562 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received_locked");
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001563 call_error = grpc_call_start_batch_and_execute(
1564 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1565 &glb_policy->lb_on_response_received);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001566 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001567}
1568
Craig Tillerbaa14a92017-11-03 09:09:36 -07001569static void lb_on_response_received_locked(grpc_exec_ctx* exec_ctx, void* arg,
1570 grpc_error* error) {
1571 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001572 grpc_op ops[2];
1573 memset(ops, 0, sizeof(ops));
Craig Tillerbaa14a92017-11-03 09:09:36 -07001574 grpc_op* op = ops;
Craig Tiller4782d922017-11-10 09:53:21 -08001575 if (glb_policy->lb_response_payload != nullptr) {
Craig Tillerc0df1c02017-07-17 16:12:33 -07001576 grpc_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001577 /* Received data from the LB server. Look inside
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001578 * glb_policy->lb_response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001579 grpc_byte_buffer_reader bbr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001580 grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001581 grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas97e17852017-08-14 14:55:02 -07001582 grpc_byte_buffer_reader_destroy(&bbr);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001583 grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001584
Craig Tiller4782d922017-11-10 09:53:21 -08001585 grpc_grpclb_initial_response* response = nullptr;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001586 if (!glb_policy->seen_initial_response &&
1587 (response = grpc_grpclb_initial_response_parse(response_slice)) !=
Craig Tiller4782d922017-11-10 09:53:21 -08001588 nullptr) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001589 if (response->has_client_stats_report_interval) {
Craig Tillerc0df1c02017-07-17 16:12:33 -07001590 glb_policy->client_stats_report_interval = GPR_MAX(
1591 GPR_MS_PER_SEC, grpc_grpclb_duration_to_millis(
1592 &response->client_stats_report_interval));
Craig Tiller84f75d42017-05-03 13:06:35 -07001593 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001594 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001595 "[grpclb %p] Received initial LB response message; "
Craig Tillerc0df1c02017-07-17 16:12:33 -07001596 "client load reporting interval = %" PRIdPTR " milliseconds",
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001597 glb_policy, glb_policy->client_stats_report_interval);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001598 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001599 /* take a weak ref (won't prevent calling of \a glb_shutdown() if the
1600 * strong ref count goes to zero) to be unref'd in
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001601 * send_client_load_report_locked() */
Mark D. Roth09e458c2017-05-02 08:13:26 -07001602 glb_policy->client_load_report_timer_pending = true;
1603 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "client_load_report");
1604 schedule_next_client_load_report(exec_ctx, glb_policy);
Craig Tiller84f75d42017-05-03 13:06:35 -07001605 } else if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001606 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001607 "[grpclb %p] Received initial LB response message; client load "
1608 "reporting NOT enabled",
1609 glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001610 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001611 grpc_grpclb_initial_response_destroy(response);
1612 glb_policy->seen_initial_response = true;
1613 } else {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001614 grpc_grpclb_serverlist* serverlist =
Mark D. Roth09e458c2017-05-02 08:13:26 -07001615 grpc_grpclb_response_parse_serverlist(response_slice);
Craig Tiller4782d922017-11-10 09:53:21 -08001616 if (serverlist != nullptr) {
1617 GPR_ASSERT(glb_policy->lb_call != nullptr);
Craig Tiller84f75d42017-05-03 13:06:35 -07001618 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001619 gpr_log(GPR_INFO,
1620 "[grpclb %p] Serverlist with %" PRIuPTR " servers received",
1621 glb_policy, serverlist->num_servers);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001622 for (size_t i = 0; i < serverlist->num_servers; ++i) {
1623 grpc_resolved_address addr;
1624 parse_server(serverlist->servers[i], &addr);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001625 char* ipport;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001626 grpc_sockaddr_to_string(&ipport, &addr, false);
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001627 gpr_log(GPR_INFO, "[grpclb %p] Serverlist[%" PRIuPTR "]: %s",
1628 glb_policy, i, ipport);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001629 gpr_free(ipport);
1630 }
1631 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001632 /* update serverlist */
1633 if (serverlist->num_servers > 0) {
1634 if (grpc_grpclb_serverlist_equals(glb_policy->serverlist,
1635 serverlist)) {
Craig Tiller84f75d42017-05-03 13:06:35 -07001636 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001637 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001638 "[grpclb %p] Incoming server list identical to current, "
1639 "ignoring.",
1640 glb_policy);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001641 }
1642 grpc_grpclb_destroy_serverlist(serverlist);
1643 } else { /* new serverlist */
Craig Tiller4782d922017-11-10 09:53:21 -08001644 if (glb_policy->serverlist != nullptr) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001645 /* dispose of the old serverlist */
1646 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
Juanli Shenfe408152017-09-27 12:27:20 -07001647 } else {
1648 /* or dispose of the fallback */
1649 grpc_lb_addresses_destroy(exec_ctx,
1650 glb_policy->fallback_backend_addresses);
Craig Tiller4782d922017-11-10 09:53:21 -08001651 glb_policy->fallback_backend_addresses = nullptr;
Juanli Shenfe408152017-09-27 12:27:20 -07001652 if (glb_policy->fallback_timer_active) {
1653 grpc_timer_cancel(exec_ctx, &glb_policy->lb_fallback_timer);
1654 glb_policy->fallback_timer_active = false;
1655 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001656 }
1657 /* and update the copy in the glb_lb_policy instance. This
1658 * serverlist instance will be destroyed either upon the next
1659 * update or in glb_destroy() */
1660 glb_policy->serverlist = serverlist;
Mark D. Rothd7389b42017-05-17 12:22:17 -07001661 glb_policy->serverlist_index = 0;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001662 rr_handover_locked(exec_ctx, glb_policy);
1663 }
1664 } else {
Craig Tiller84f75d42017-05-03 13:06:35 -07001665 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001666 gpr_log(GPR_INFO,
1667 "[grpclb %p] Received empty server list, ignoring.",
1668 glb_policy);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001669 }
1670 grpc_grpclb_destroy_serverlist(serverlist);
1671 }
1672 } else { /* serverlist == NULL */
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001673 gpr_log(GPR_ERROR,
1674 "[grpclb %p] Invalid LB response received: '%s'. Ignoring.",
1675 glb_policy,
Mark D. Roth09e458c2017-05-02 08:13:26 -07001676 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
1677 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001678 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001679 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas246c5642016-11-01 11:16:52 -07001680 if (!glb_policy->shutting_down) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001681 /* keep listening for serverlist updates */
1682 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001683 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001684 op->flags = 0;
Craig Tiller4782d922017-11-10 09:53:21 -08001685 op->reserved = nullptr;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001686 op++;
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001687 /* reuse the "lb_on_response_received_locked" weak ref taken in
David Garcia Quintase224a762016-11-01 13:00:58 -07001688 * query_for_backends_locked() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001689 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas246c5642016-11-01 11:16:52 -07001690 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1691 &glb_policy->lb_on_response_received); /* loop */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001692 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas998bd2c2017-09-18 12:41:07 -07001693 } else {
1694 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1695 "lb_on_response_received_locked_shutdown");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001696 }
David Garcia Quintase224a762016-11-01 13:00:58 -07001697 } else { /* empty payload: call cancelled. */
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001698 /* dispose of the "lb_on_response_received_locked" weak ref taken in
David Garcia Quintase224a762016-11-01 13:00:58 -07001699 * query_for_backends_locked() and reused in every reception loop */
1700 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001701 "lb_on_response_received_locked_empty_payload");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001702 }
1703}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001704
Craig Tillerbaa14a92017-11-03 09:09:36 -07001705static void lb_on_fallback_timer_locked(grpc_exec_ctx* exec_ctx, void* arg,
1706 grpc_error* error) {
1707 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Juanli Shenfe408152017-09-27 12:27:20 -07001708 glb_policy->fallback_timer_active = false;
1709 /* If we receive a serverlist after the timer fires but before this callback
1710 * actually runs, don't fall back. */
Craig Tiller4782d922017-11-10 09:53:21 -08001711 if (glb_policy->serverlist == nullptr) {
Juanli Shenfe408152017-09-27 12:27:20 -07001712 if (!glb_policy->shutting_down && error == GRPC_ERROR_NONE) {
1713 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
1714 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001715 "[grpclb %p] Falling back to use backends from resolver",
1716 glb_policy);
Juanli Shenfe408152017-09-27 12:27:20 -07001717 }
Craig Tiller4782d922017-11-10 09:53:21 -08001718 GPR_ASSERT(glb_policy->fallback_backend_addresses != nullptr);
Juanli Shenfe408152017-09-27 12:27:20 -07001719 rr_handover_locked(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001720 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001721 }
Juanli Shenfe408152017-09-27 12:27:20 -07001722 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1723 "grpclb_fallback_timer");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001724}
1725
Craig Tillerbaa14a92017-11-03 09:09:36 -07001726static void lb_on_server_status_received_locked(grpc_exec_ctx* exec_ctx,
1727 void* arg, grpc_error* error) {
1728 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Craig Tiller4782d922017-11-10 09:53:21 -08001729 GPR_ASSERT(glb_policy->lb_call != nullptr);
Craig Tiller84f75d42017-05-03 13:06:35 -07001730 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001731 char* status_details =
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001732 grpc_slice_to_c_string(glb_policy->lb_call_status_details);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001733 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001734 "[grpclb %p] Status from LB server received. Status = %d, Details "
David Garcia Quintas2b372e02017-11-09 14:15:59 -08001735 "= '%s', (call: %p), error '%s'",
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001736 glb_policy, glb_policy->lb_call_status, status_details,
David Garcia Quintas2b372e02017-11-09 14:15:59 -08001737 glb_policy->lb_call, grpc_error_string(error));
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001738 gpr_free(status_details);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001739 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001740 /* We need to perform cleanups no matter what. */
1741 lb_call_destroy_locked(exec_ctx, glb_policy);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001742 // If the load report timer is still pending, we wait for it to be
1743 // called before restarting the call. Otherwise, we restart the call
1744 // here.
1745 if (!glb_policy->client_load_report_timer_pending) {
1746 maybe_restart_lb_call(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001747 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001748}
1749
Craig Tillerbaa14a92017-11-03 09:09:36 -07001750static void fallback_update_locked(grpc_exec_ctx* exec_ctx,
1751 glb_lb_policy* glb_policy,
1752 const grpc_lb_addresses* addresses) {
Craig Tiller4782d922017-11-10 09:53:21 -08001753 GPR_ASSERT(glb_policy->fallback_backend_addresses != nullptr);
Juanli Shenfe408152017-09-27 12:27:20 -07001754 grpc_lb_addresses_destroy(exec_ctx, glb_policy->fallback_backend_addresses);
1755 glb_policy->fallback_backend_addresses =
1756 extract_backend_addresses_locked(exec_ctx, addresses);
David Garcia Quintas3f69cb32017-11-09 14:38:58 -08001757 if (glb_policy->started_picking && glb_policy->lb_fallback_timeout_ms > 0 &&
Juanli Shenfe408152017-09-27 12:27:20 -07001758 !glb_policy->fallback_timer_active) {
1759 rr_handover_locked(exec_ctx, glb_policy);
1760 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001761}
1762
Craig Tillerbaa14a92017-11-03 09:09:36 -07001763static void glb_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
1764 const grpc_lb_policy_args* args) {
1765 glb_lb_policy* glb_policy = (glb_lb_policy*)policy;
1766 const grpc_arg* arg =
Juanli Shenfe408152017-09-27 12:27:20 -07001767 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
Craig Tiller4782d922017-11-10 09:53:21 -08001768 if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
1769 if (glb_policy->lb_channel == nullptr) {
Juanli Shenfe408152017-09-27 12:27:20 -07001770 // If we don't have a current channel to the LB, go into TRANSIENT
1771 // FAILURE.
1772 grpc_connectivity_state_set(
1773 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
1774 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"),
1775 "glb_update_missing");
1776 } else {
1777 // otherwise, keep using the current LB channel (ignore this update).
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001778 gpr_log(
1779 GPR_ERROR,
1780 "[grpclb %p] No valid LB addresses channel arg in update, ignoring.",
1781 glb_policy);
Juanli Shenfe408152017-09-27 12:27:20 -07001782 }
1783 return;
1784 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001785 const grpc_lb_addresses* addresses =
1786 (const grpc_lb_addresses*)arg->value.pointer.p;
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001787 // If a non-empty serverlist hasn't been received from the balancer,
1788 // propagate the update to fallback_backend_addresses.
Craig Tiller4782d922017-11-10 09:53:21 -08001789 if (glb_policy->serverlist == nullptr) {
Juanli Shenfe408152017-09-27 12:27:20 -07001790 fallback_update_locked(exec_ctx, glb_policy, addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001791 }
Craig Tiller4782d922017-11-10 09:53:21 -08001792 GPR_ASSERT(glb_policy->lb_channel != nullptr);
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001793 // Propagate updates to the LB channel (pick_first) through the fake
1794 // resolver.
Craig Tillerbaa14a92017-11-03 09:09:36 -07001795 grpc_channel_args* lb_channel_args = build_lb_channel_args(
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001796 exec_ctx, addresses, glb_policy->response_generator, args->args);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001797 grpc_fake_resolver_response_generator_set_response(
1798 exec_ctx, glb_policy->response_generator, lb_channel_args);
1799 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001800 // Start watching the LB channel connectivity for connection, if not
1801 // already doing so.
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001802 if (!glb_policy->watching_lb_channel) {
David Garcia Quintas6a7935e2017-07-27 19:24:52 -07001803 glb_policy->lb_channel_connectivity = grpc_channel_check_connectivity_state(
1804 glb_policy->lb_channel, true /* try to connect */);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001805 grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001806 grpc_channel_get_channel_stack(glb_policy->lb_channel));
1807 GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1808 glb_policy->watching_lb_channel = true;
1809 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "watch_lb_channel_connectivity");
1810 grpc_client_channel_watch_connectivity_state(
1811 exec_ctx, client_channel_elem,
1812 grpc_polling_entity_create_from_pollset_set(
1813 glb_policy->base.interested_parties),
1814 &glb_policy->lb_channel_connectivity,
Craig Tiller4782d922017-11-10 09:53:21 -08001815 &glb_policy->lb_channel_on_connectivity_changed, nullptr);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001816 }
1817}
1818
1819// Invoked as part of the update process. It continues watching the LB channel
1820// until it shuts down or becomes READY. It's invoked even if the LB channel
1821// stayed READY throughout the update (for example if the update is identical).
Craig Tillerbaa14a92017-11-03 09:09:36 -07001822static void glb_lb_channel_on_connectivity_changed_cb(grpc_exec_ctx* exec_ctx,
1823 void* arg,
1824 grpc_error* error) {
1825 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001826 if (glb_policy->shutting_down) goto done;
1827 // Re-initialize the lb_call. This should also take care of updating the
1828 // embedded RR policy. Note that the current RR policy, if any, will stay in
1829 // effect until an update from the new lb_call is received.
1830 switch (glb_policy->lb_channel_connectivity) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001831 case GRPC_CHANNEL_CONNECTING:
1832 case GRPC_CHANNEL_TRANSIENT_FAILURE: {
1833 /* resub. */
Craig Tillerbaa14a92017-11-03 09:09:36 -07001834 grpc_channel_element* client_channel_elem =
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001835 grpc_channel_stack_last_element(
1836 grpc_channel_get_channel_stack(glb_policy->lb_channel));
1837 GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1838 grpc_client_channel_watch_connectivity_state(
1839 exec_ctx, client_channel_elem,
1840 grpc_polling_entity_create_from_pollset_set(
1841 glb_policy->base.interested_parties),
1842 &glb_policy->lb_channel_connectivity,
Craig Tiller4782d922017-11-10 09:53:21 -08001843 &glb_policy->lb_channel_on_connectivity_changed, nullptr);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001844 break;
1845 }
1846 case GRPC_CHANNEL_IDLE:
David Garcia Quintas2b217d42017-10-20 15:56:30 -07001847 // lb channel inactive (probably shutdown prior to update). Restart lb
1848 // call to kick the lb channel into gear.
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001849 /* fallthrough */
1850 case GRPC_CHANNEL_READY:
Craig Tiller4782d922017-11-10 09:53:21 -08001851 if (glb_policy->lb_call != nullptr) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001852 glb_policy->updating_lb_call = true;
Craig Tiller4782d922017-11-10 09:53:21 -08001853 grpc_call_cancel(glb_policy->lb_call, nullptr);
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001854 // lb_on_server_status_received() will pick up the cancel and reinit
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001855 // lb_call.
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001856 } else if (glb_policy->started_picking && !glb_policy->shutting_down) {
1857 if (glb_policy->retry_timer_active) {
1858 grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
1859 glb_policy->retry_timer_active = false;
1860 }
1861 start_picking_locked(exec_ctx, glb_policy);
1862 }
1863 /* fallthrough */
1864 case GRPC_CHANNEL_SHUTDOWN:
1865 done:
1866 glb_policy->watching_lb_channel = false;
1867 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1868 "watch_lb_channel_connectivity_cb_shutdown");
1869 break;
1870 }
1871}
1872
David Garcia Quintas8d489112016-07-29 15:20:42 -07001873/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001874static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
Craig Tiller2400bf52017-02-09 16:25:19 -08001875 glb_destroy,
1876 glb_shutdown_locked,
1877 glb_pick_locked,
1878 glb_cancel_pick_locked,
1879 glb_cancel_picks_locked,
1880 glb_ping_one_locked,
1881 glb_exit_idle_locked,
1882 glb_check_connectivity_locked,
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001883 glb_notify_on_state_change_locked,
1884 glb_update_locked};
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001885
Craig Tillerbaa14a92017-11-03 09:09:36 -07001886static grpc_lb_policy* glb_create(grpc_exec_ctx* exec_ctx,
1887 grpc_lb_policy_factory* factory,
1888 grpc_lb_policy_args* args) {
Juanli Shenfe408152017-09-27 12:27:20 -07001889 /* Count the number of gRPC-LB addresses. There must be at least one. */
Craig Tillerbaa14a92017-11-03 09:09:36 -07001890 const grpc_arg* arg =
Yash Tibrewala4952202017-09-13 10:53:28 -07001891 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
Craig Tiller4782d922017-11-10 09:53:21 -08001892 if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
1893 return nullptr;
Yash Tibrewala4952202017-09-13 10:53:28 -07001894 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001895 grpc_lb_addresses* addresses = (grpc_lb_addresses*)arg->value.pointer.p;
Yash Tibrewala4952202017-09-13 10:53:28 -07001896 size_t num_grpclb_addrs = 0;
1897 for (size_t i = 0; i < addresses->num_addresses; ++i) {
1898 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
1899 }
Craig Tiller4782d922017-11-10 09:53:21 -08001900 if (num_grpclb_addrs == 0) return nullptr;
Yash Tibrewala4952202017-09-13 10:53:28 -07001901
Craig Tillerbaa14a92017-11-03 09:09:36 -07001902 glb_lb_policy* glb_policy = (glb_lb_policy*)gpr_zalloc(sizeof(*glb_policy));
Yash Tibrewala4952202017-09-13 10:53:28 -07001903
1904 /* Get server name. */
1905 arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
Craig Tiller4782d922017-11-10 09:53:21 -08001906 GPR_ASSERT(arg != nullptr);
Yash Tibrewala4952202017-09-13 10:53:28 -07001907 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001908 grpc_uri* uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
Yash Tibrewala4952202017-09-13 10:53:28 -07001909 GPR_ASSERT(uri->path[0] != '\0');
1910 glb_policy->server_name =
1911 gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
1912 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001913 gpr_log(GPR_INFO,
1914 "[grpclb %p] Will use '%s' as the server name for LB request.",
1915 glb_policy, glb_policy->server_name);
Yash Tibrewala4952202017-09-13 10:53:28 -07001916 }
1917 grpc_uri_destroy(uri);
1918
1919 glb_policy->cc_factory = args->client_channel_factory;
Craig Tiller4782d922017-11-10 09:53:21 -08001920 GPR_ASSERT(glb_policy->cc_factory != nullptr);
Yash Tibrewala4952202017-09-13 10:53:28 -07001921
1922 arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS);
1923 glb_policy->lb_call_timeout_ms =
Yash Tibrewald8b84a22017-09-25 13:38:03 -07001924 grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX});
Yash Tibrewala4952202017-09-13 10:53:28 -07001925
Juanli Shenfe408152017-09-27 12:27:20 -07001926 arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS);
1927 glb_policy->lb_fallback_timeout_ms = grpc_channel_arg_get_integer(
Yash Tibrewal1150bfb2017-09-28 14:43:41 -07001928 arg, {GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX});
Juanli Shenfe408152017-09-27 12:27:20 -07001929
Yash Tibrewala4952202017-09-13 10:53:28 -07001930 // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
1931 // since we use this to trigger the client_load_reporting filter.
Yash Tibrewal9eb86722017-09-17 23:43:30 -07001932 grpc_arg new_arg = grpc_channel_arg_string_create(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001933 (char*)GRPC_ARG_LB_POLICY_NAME, (char*)"grpclb");
1934 static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
Yash Tibrewala4952202017-09-13 10:53:28 -07001935 glb_policy->args = grpc_channel_args_copy_and_add_and_remove(
1936 args->args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
1937
Juanli Shenfe408152017-09-27 12:27:20 -07001938 /* Extract the backend addresses (may be empty) from the resolver for
1939 * fallback. */
1940 glb_policy->fallback_backend_addresses =
1941 extract_backend_addresses_locked(exec_ctx, addresses);
1942
Yash Tibrewala4952202017-09-13 10:53:28 -07001943 /* Create a client channel over them to communicate with a LB service */
1944 glb_policy->response_generator =
1945 grpc_fake_resolver_response_generator_create();
Craig Tillerbaa14a92017-11-03 09:09:36 -07001946 grpc_channel_args* lb_channel_args = build_lb_channel_args(
Yash Tibrewala4952202017-09-13 10:53:28 -07001947 exec_ctx, addresses, glb_policy->response_generator, args->args);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001948 char* uri_str;
Yash Tibrewala4952202017-09-13 10:53:28 -07001949 gpr_asprintf(&uri_str, "fake:///%s", glb_policy->server_name);
1950 glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
1951 exec_ctx, uri_str, args->client_channel_factory, lb_channel_args);
1952
1953 /* Propagate initial resolution */
1954 grpc_fake_resolver_response_generator_set_response(
1955 exec_ctx, glb_policy->response_generator, lb_channel_args);
1956 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
1957 gpr_free(uri_str);
Craig Tiller4782d922017-11-10 09:53:21 -08001958 if (glb_policy->lb_channel == nullptr) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001959 gpr_free((void*)glb_policy->server_name);
Yash Tibrewala4952202017-09-13 10:53:28 -07001960 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
1961 gpr_free(glb_policy);
Craig Tiller4782d922017-11-10 09:53:21 -08001962 return nullptr;
Yash Tibrewala4952202017-09-13 10:53:28 -07001963 }
Ken Payson9fa10cc2017-09-14 11:49:52 -07001964 grpc_subchannel_index_ref();
Yash Tibrewala4952202017-09-13 10:53:28 -07001965 GRPC_CLOSURE_INIT(&glb_policy->lb_channel_on_connectivity_changed,
1966 glb_lb_channel_on_connectivity_changed_cb, glb_policy,
1967 grpc_combiner_scheduler(args->combiner));
1968 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
1969 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
1970 "grpclb");
1971 return &glb_policy->base;
1972}
1973
Craig Tillerbaa14a92017-11-03 09:09:36 -07001974static void glb_factory_ref(grpc_lb_policy_factory* factory) {}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001975
Craig Tillerbaa14a92017-11-03 09:09:36 -07001976static void glb_factory_unref(grpc_lb_policy_factory* factory) {}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001977
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001978static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1979 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1980
1981static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1982
Craig Tillerbaa14a92017-11-03 09:09:36 -07001983grpc_lb_policy_factory* grpc_glb_lb_factory_create() {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001984 return &glb_lb_policy_factory;
1985}
1986
1987/* Plugin registration */
Mark D. Roth09e458c2017-05-02 08:13:26 -07001988
1989// Only add client_load_reporting filter if the grpclb LB policy is used.
1990static bool maybe_add_client_load_reporting_filter(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001991 grpc_exec_ctx* exec_ctx, grpc_channel_stack_builder* builder, void* arg) {
1992 const grpc_channel_args* args =
Mark D. Roth09e458c2017-05-02 08:13:26 -07001993 grpc_channel_stack_builder_get_channel_arguments(builder);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001994 const grpc_arg* channel_arg =
Mark D. Roth09e458c2017-05-02 08:13:26 -07001995 grpc_channel_args_find(args, GRPC_ARG_LB_POLICY_NAME);
Craig Tiller4782d922017-11-10 09:53:21 -08001996 if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_STRING &&
Mark D. Roth09e458c2017-05-02 08:13:26 -07001997 strcmp(channel_arg->value.string, "grpclb") == 0) {
1998 return grpc_channel_stack_builder_append_filter(
Craig Tiller4782d922017-11-10 09:53:21 -08001999 builder, (const grpc_channel_filter*)arg, nullptr, nullptr);
Mark D. Roth09e458c2017-05-02 08:13:26 -07002000 }
2001 return true;
2002}
2003
ncteisenadbfbd52017-11-16 15:35:45 -08002004void grpc_lb_policy_grpclb_init() {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07002005 grpc_register_lb_policy(grpc_glb_lb_factory_create());
ncteisen06bce6e2017-07-10 07:58:49 -07002006 grpc_register_tracer(&grpc_lb_glb_trace);
ncteisen4b584052017-06-08 16:44:38 -07002007#ifndef NDEBUG
ncteisen06bce6e2017-07-10 07:58:49 -07002008 grpc_register_tracer(&grpc_trace_lb_policy_refcount);
ncteisen4b584052017-06-08 16:44:38 -07002009#endif
Mark D. Roth09e458c2017-05-02 08:13:26 -07002010 grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
2011 GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
2012 maybe_add_client_load_reporting_filter,
Craig Tillerbaa14a92017-11-03 09:09:36 -07002013 (void*)&grpc_client_load_reporting_filter);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07002014}
2015
ncteisenadbfbd52017-11-16 15:35:45 -08002016void grpc_lb_policy_grpclb_shutdown() {}