blob: ded457f64a8e5baa96d95f3d04e7191aba6d16b2 [file] [log] [blame]
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001/*
2 *
3 * Copyright 2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070034/** Implementation of the gRPC LB policy.
35 *
David Garcia Quintas43339842016-07-18 12:56:09 -070036 * This policy takes as input a set of resolved addresses {a1..an} for which the
37 * LB set was set (it's the resolver's responsibility to ensure this). That is
38 * to say, {a1..an} represent a collection of LB servers.
39 *
40 * An internal channel (\a glb_lb_policy.lb_channel) is created over {a1..an}.
41 * This channel behaves just like a regular channel. In particular, the
42 * constructed URI over the addresses a1..an will use the default pick first
43 * policy to select from this list of LB server backends.
44 *
David Garcia Quintas41bef452016-07-28 19:19:58 -070045 * 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 +020046 * idle state, \a query_for_backends_locked() is called. This function sets up
47 * and initiates the internal communication with the LB server. In particular,
48 * it's responsible for instantiating the internal *streaming* call to the LB
49 * server (whichever address from {a1..an} pick-first chose). This call is
David Garcia Quintas7ec29132016-11-01 04:09:05 +010050 * serviced by two callbacks, \a lb_on_server_status_received and \a
51 * lb_on_response_received. The former will be called when the call to the LB
52 * server completes. This can happen if the LB server closes the connection or
53 * if this policy itself cancels the call (for example because it's shutting
David Garcia Quintas246c5642016-11-01 11:16:52 -070054 * down). If the internal call times out, the usual behavior of pick-first
David Garcia Quintas7ec29132016-11-01 04:09:05 +010055 * applies, continuing to pick from the list {a1..an}.
David Garcia Quintas43339842016-07-18 12:56:09 -070056 *
David Garcia Quintas98da61b2016-10-29 08:46:31 +020057 * Upon sucesss, the incoming \a LoadBalancingResponse is processed by \a
58 * res_recv. An invalid one results in the termination of the streaming call. A
59 * new streaming call should be created if possible, failing the original call
60 * otherwise. For a valid \a LoadBalancingResponse, the server list of actual
61 * backends is extracted. A Round Robin policy will be created from this list.
62 * There are two possible scenarios:
David Garcia Quintas43339842016-07-18 12:56:09 -070063 *
64 * 1. This is the first server list received. There was no previous instance of
David Garcia Quintas90712d52016-10-13 19:33:04 -070065 * the Round Robin policy. \a rr_handover_locked() will instantiate the RR
66 * policy and perform all the pending operations over it.
David Garcia Quintas43339842016-07-18 12:56:09 -070067 * 2. There's already a RR policy instance active. We need to introduce the new
68 * one build from the new serverlist, but taking care not to disrupt the
69 * operations in progress over the old RR instance. This is done by
70 * decreasing the reference count on the old policy. The moment no more
71 * references are held on the old RR policy, it'll be destroyed and \a
David Garcia Quintas348cfdb2016-08-19 12:19:43 -070072 * glb_rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN
73 * state. At this point we can transition to a new RR instance safely, which
David Garcia Quintas90712d52016-10-13 19:33:04 -070074 * is done once again via \a rr_handover_locked().
David Garcia Quintas43339842016-07-18 12:56:09 -070075 *
76 *
77 * Once a RR policy instance is in place (and getting updated as described),
78 * calls to for a pick, a ping or a cancellation will be serviced right away by
79 * forwarding them to the RR instance. Any time there's no RR policy available
David Garcia Quintas7ec29132016-11-01 04:09:05 +010080 * (ie, right after the creation of the gRPCLB policy, if an empty serverlist is
81 * received, etc), pick/ping requests are added to a list of pending picks/pings
82 * to be flushed and serviced as part of \a rr_handover_locked() the moment the
83 * RR policy instance becomes available.
David Garcia Quintas43339842016-07-18 12:56:09 -070084 *
85 * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the
86 * high level design and details. */
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070087
88/* TODO(dgq):
89 * - Implement LB service forwarding (point 2c. in the doc's diagram).
90 */
91
murgatroid99085f9af2016-10-24 09:55:44 -070092/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
93 using that endpoint. Because of various transitive includes in uv.h,
94 including windows.h on Windows, uv.h must be included before other system
95 headers. Therefore, sockaddr.h must always be included first */
murgatroid997871f732016-09-23 13:49:05 -070096#include "src/core/lib/iomgr/sockaddr.h"
97
David Garcia Quintas8a81aa12016-08-22 15:06:49 -070098#include <errno.h>
99
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -0700100#include <string.h>
101
102#include <grpc/byte_buffer_reader.h>
103#include <grpc/grpc.h>
104#include <grpc/support/alloc.h>
105#include <grpc/support/host_port.h>
106#include <grpc/support/string_util.h>
David Garcia Quintas69099222016-10-03 11:28:37 -0700107#include <grpc/support/time.h>
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -0700108
Mark D. Rothbe5e3ca2016-12-12 09:58:20 -0800109#include "src/core/ext/client_channel/client_channel.h"
Mark D. Roth2137cd82016-09-14 09:04:00 -0700110#include "src/core/ext/client_channel/client_channel_factory.h"
Mark D. Roth15195742016-10-07 09:02:28 -0700111#include "src/core/ext/client_channel/lb_policy_factory.h"
Mark D. Roth2137cd82016-09-14 09:04:00 -0700112#include "src/core/ext/client_channel/lb_policy_registry.h"
113#include "src/core/ext/client_channel/parse_address.h"
David Garcia Quintas8782d1b2016-06-15 23:58:44 -0700114#include "src/core/ext/lb_policy/grpclb/grpclb.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700115#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
Mark D. Roth046cf762016-09-26 11:13:51 -0700116#include "src/core/lib/channel/channel_args.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200117#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700118#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200119#include "src/core/lib/iomgr/timer.h"
Craig Tiller18b4ba32016-11-09 15:23:42 -0800120#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -0700121#include "src/core/lib/slice/slice_string_helpers.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200122#include "src/core/lib/support/backoff.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700123#include "src/core/lib/support/string.h"
124#include "src/core/lib/surface/call.h"
125#include "src/core/lib/surface/channel.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700126#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700127
David Garcia Quintas1edfb952016-11-22 17:15:34 -0800128#define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20
129#define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1
130#define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6
131#define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
132#define GRPC_GRPCLB_RECONNECT_JITTER 0.2
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200133
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700134int grpc_lb_glb_trace = 0;
135
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700136/* add lb_token of selected subchannel (address) to the call's initial
137 * metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800138static grpc_error *initial_metadata_add_lb_token(
139 grpc_exec_ctx *exec_ctx, grpc_metadata_batch *initial_metadata,
140 grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700141 GPR_ASSERT(lb_token_mdelem_storage != NULL);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800142 GPR_ASSERT(!GRPC_MDISNULL(lb_token));
143 return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
144 lb_token_mdelem_storage, lb_token);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700145}
146
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700147typedef struct wrapped_rr_closure_arg {
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700148 /* the closure instance using this struct as argument */
149 grpc_closure wrapper_closure;
150
David Garcia Quintas43339842016-07-18 12:56:09 -0700151 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
152 * calls against the internal RR instance, respectively. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700153 grpc_closure *wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700154
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700155 /* the pick's initial metadata, kept in order to append the LB token for the
156 * pick */
157 grpc_metadata_batch *initial_metadata;
158
159 /* the picked target, used to determine which LB token to add to the pick's
160 * initial metadata */
161 grpc_connected_subchannel **target;
162
163 /* the LB token associated with the pick */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800164 grpc_mdelem lb_token;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700165
166 /* storage for the lb token initial metadata mdelem */
167 grpc_linked_mdelem *lb_token_mdelem_storage;
168
David Garcia Quintas43339842016-07-18 12:56:09 -0700169 /* The RR instance related to the closure */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700170 grpc_lb_policy *rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700171
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700172 /* heap memory to be freed upon closure execution. */
173 void *free_when_done;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700174} wrapped_rr_closure_arg;
175
176/* The \a on_complete closure passed as part of the pick requires keeping a
177 * reference to its associated round robin instance. We wrap this closure in
178 * order to unref the round robin instance upon its invocation */
179static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700180 grpc_error *error) {
David Garcia Quintas43339842016-07-18 12:56:09 -0700181 wrapped_rr_closure_arg *wc_arg = arg;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700182
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200183 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
Craig Tiller91031da2016-12-28 15:44:25 -0800184 grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200185
186 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas6493a732016-11-22 10:25:52 -0800187 /* if *target is NULL, no pick has been made by the RR policy (eg, all
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700188 * addresses failed to connect). There won't be any user_data/token
189 * available */
David Garcia Quintas6493a732016-11-22 10:25:52 -0800190 if (*wc_arg->target != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800191 if (!GRPC_MDISNULL(wc_arg->lb_token)) {
192 initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800193 wc_arg->lb_token_mdelem_storage,
194 GRPC_MDELEM_REF(wc_arg->lb_token));
195 } else {
196 gpr_log(GPR_ERROR,
197 "No LB token for connected subchannel pick %p (from RR "
198 "instance %p).",
199 (void *)*wc_arg->target, (void *)wc_arg->rr_policy);
200 abort();
201 }
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700202 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200203 if (grpc_lb_glb_trace) {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800204 gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200205 }
206 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700207 }
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700208 GPR_ASSERT(wc_arg->free_when_done != NULL);
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700209 gpr_free(wc_arg->free_when_done);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700210}
211
David Garcia Quintasea11d162016-07-14 17:27:28 -0700212/* Linked list of pending pick requests. It stores all information needed to
213 * eventually call (Round Robin's) pick() on them. They mainly stay pending
214 * waiting for the RR policy to be created/updated.
215 *
216 * One particularity is the wrapping of the user-provided \a on_complete closure
217 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
218 * order to correctly unref the RR policy instance upon completion of the pick.
219 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700220typedef struct pending_pick {
221 struct pending_pick *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700222
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700223 /* original pick()'s arguments */
224 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700225
226 /* output argument where to store the pick()ed connected subchannel, or NULL
227 * upon error. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700228 grpc_connected_subchannel **target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700229
David Garcia Quintas43339842016-07-18 12:56:09 -0700230 /* args for wrapped_on_complete */
231 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700232} pending_pick;
233
David Garcia Quintas8aace512016-08-15 14:55:12 -0700234static void add_pending_pick(pending_pick **root,
235 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas65318262016-07-29 13:43:38 -0700236 grpc_connected_subchannel **target,
237 grpc_closure *on_complete) {
238 pending_pick *pp = gpr_malloc(sizeof(*pp));
239 memset(pp, 0, sizeof(pending_pick));
240 memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
241 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700242 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700243 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700244 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700245 pp->wrapped_on_complete_arg.target = target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700246 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
247 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
248 pick_args->lb_token_mdelem_storage;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700249 pp->wrapped_on_complete_arg.free_when_done = pp;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700250 grpc_closure_init(&pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800251 wrapped_rr_closure, &pp->wrapped_on_complete_arg,
252 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700253 *root = pp;
254}
255
David Garcia Quintasea11d162016-07-14 17:27:28 -0700256/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700257typedef struct pending_ping {
258 struct pending_ping *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700259
David Garcia Quintas43339842016-07-18 12:56:09 -0700260 /* args for wrapped_notify */
261 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700262} pending_ping;
263
David Garcia Quintas65318262016-07-29 13:43:38 -0700264static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
265 pending_ping *pping = gpr_malloc(sizeof(*pping));
266 memset(pping, 0, sizeof(pending_ping));
267 memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
David Garcia Quintas65318262016-07-29 13:43:38 -0700268 pping->wrapped_notify_arg.wrapped_closure = notify;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700269 pping->wrapped_notify_arg.free_when_done = pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700270 pping->next = *root;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700271 grpc_closure_init(&pping->wrapped_notify_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800272 wrapped_rr_closure, &pping->wrapped_notify_arg,
273 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700274 *root = pping;
275}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700276
David Garcia Quintas8d489112016-07-29 15:20:42 -0700277/*
278 * glb_lb_policy
279 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700280typedef struct rr_connectivity_data rr_connectivity_data;
David Garcia Quintas65318262016-07-29 13:43:38 -0700281static const grpc_lb_policy_vtable glb_lb_policy_vtable;
282typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700283 /** base policy: must be first */
284 grpc_lb_policy base;
285
286 /** mutex protecting remaining members */
287 gpr_mu mu;
288
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700289 /** who the client is trying to communicate with */
Mark D. Rothd1604af2016-09-22 11:20:27 -0700290 const char *server_name;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700291 grpc_client_channel_factory *cc_factory;
Mark D. Roth046cf762016-09-26 11:13:51 -0700292 grpc_channel_args *args;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700293
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700294 /** deadline for the LB's call */
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700295 gpr_timespec deadline;
296
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700297 /** for communicating with the LB server */
David Garcia Quintasea11d162016-07-14 17:27:28 -0700298 grpc_channel *lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700299
300 /** the RR policy to use of the backend servers returned by the LB server */
301 grpc_lb_policy *rr_policy;
302
303 bool started_picking;
304
305 /** our connectivity state tracker */
306 grpc_connectivity_state_tracker state_tracker;
307
David Garcia Quintasea11d162016-07-14 17:27:28 -0700308 /** stores the deserialized response from the LB. May be NULL until one such
309 * response has arrived. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700310 grpc_grpclb_serverlist *serverlist;
311
David Garcia Quintasea11d162016-07-14 17:27:28 -0700312 /** list of picks that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700313 pending_pick *pending_picks;
314
David Garcia Quintasea11d162016-07-14 17:27:28 -0700315 /** list of pings that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700316 pending_ping *pending_pings;
317
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200318 bool shutting_down;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700319
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200320 /************************************************************/
321 /* client data associated with the LB server communication */
322 /************************************************************/
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100323 /* Status from the LB server has been received. This signals the end of the LB
324 * call. */
325 grpc_closure lb_on_server_status_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200326
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100327 /* A response from the LB server has been received. Process it */
328 grpc_closure lb_on_response_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200329
Masood Malekghassemib5b43722017-01-05 15:07:26 -0800330 /* LB call retry timer callback. */
331 grpc_closure lb_on_call_retry;
332
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200333 grpc_call *lb_call; /* streaming call to the LB server, */
334
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100335 grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */
336 grpc_metadata_array
337 lb_trailing_metadata_recv; /* trailing MD from LB server */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200338
339 /* what's being sent to the LB server. Note that its value may vary if the LB
340 * server indicates a redirect. */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100341 grpc_byte_buffer *lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200342
David Garcia Quintas246c5642016-11-01 11:16:52 -0700343 /* response the LB server, if any. Processed in lb_on_response_received() */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100344 grpc_byte_buffer *lb_response_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200345
David Garcia Quintas246c5642016-11-01 11:16:52 -0700346 /* call status code and details, set in lb_on_server_status_received() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200347 grpc_status_code lb_call_status;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800348 grpc_slice lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200349
350 /** LB call retry backoff state */
351 gpr_backoff lb_call_backoff_state;
352
353 /** LB call retry timer */
354 grpc_timer lb_call_retry_timer;
David Garcia Quintas65318262016-07-29 13:43:38 -0700355} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700356
David Garcia Quintas65318262016-07-29 13:43:38 -0700357/* Keeps track and reacts to changes in connectivity of the RR instance */
358struct rr_connectivity_data {
359 grpc_closure on_change;
360 grpc_connectivity_state state;
361 glb_lb_policy *glb_policy;
362};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700363
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700364static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
365 bool log) {
366 const grpc_grpclb_ip_address *ip = &server->ip_address;
367 if (server->port >> 16 != 0) {
368 if (log) {
369 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200370 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
371 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700372 }
373 return false;
374 }
375
376 if (ip->size != 4 && ip->size != 16) {
377 if (log) {
378 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200379 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700380 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200381 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700382 }
383 return false;
384 }
385 return true;
386}
387
Mark D. Roth16883a32016-10-21 10:30:58 -0700388/* vtable for LB tokens in grpc_lb_addresses. */
Mark D. Roth557c9902016-10-24 11:12:05 -0700389static void *lb_token_copy(void *token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800390 return token == NULL
391 ? NULL
392 : (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload;
Mark D. Roth16883a32016-10-21 10:30:58 -0700393}
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800394static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800395 if (token != NULL) {
396 GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token});
397 }
Mark D. Roth16883a32016-10-21 10:30:58 -0700398}
Mark D. Roth557c9902016-10-24 11:12:05 -0700399static int lb_token_cmp(void *token1, void *token2) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700400 if (token1 > token2) return 1;
401 if (token1 < token2) return -1;
402 return 0;
403}
404static const grpc_lb_user_data_vtable lb_token_vtable = {
405 lb_token_copy, lb_token_destroy, lb_token_cmp};
406
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100407static void parse_server(const grpc_grpclb_server *server,
408 grpc_resolved_address *addr) {
409 const uint16_t netorder_port = htons((uint16_t)server->port);
410 /* the addresses are given in binary format (a in(6)_addr struct) in
411 * server->ip_address.bytes. */
412 const grpc_grpclb_ip_address *ip = &server->ip_address;
413 memset(addr, 0, sizeof(*addr));
414 if (ip->size == 4) {
415 addr->len = sizeof(struct sockaddr_in);
416 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
417 addr4->sin_family = AF_INET;
418 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
419 addr4->sin_port = netorder_port;
420 } else if (ip->size == 16) {
421 addr->len = sizeof(struct sockaddr_in6);
422 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr->addr;
David Garcia Quintas107ca162016-11-02 18:17:03 -0700423 addr6->sin6_family = AF_INET6;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100424 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
425 addr6->sin6_port = netorder_port;
426 }
427}
428
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700429/* Returns addresses extracted from \a serverlist. */
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800430static grpc_lb_addresses *process_serverlist_locked(
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800431 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700432 size_t num_valid = 0;
433 /* first pass: count how many are valid in order to allocate the necessary
434 * memory in a single block */
435 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700436 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700437 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700438 if (num_valid == 0) return NULL;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700439
Mark D. Roth16883a32016-10-21 10:30:58 -0700440 grpc_lb_addresses *lb_addresses =
441 grpc_lb_addresses_create(num_valid, &lb_token_vtable);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700442
443 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700444 * to the outside world) to be read by the RR policy during its creation.
445 * Given that the validity tests are very cheap, they are performed again
446 * instead of marking the valid ones during the first pass, as this would
447 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700448 size_t addr_idx = 0;
449 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
450 GPR_ASSERT(addr_idx < num_valid);
451 const grpc_grpclb_server *server = serverlist->servers[sl_idx];
452 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700453
454 /* address processing */
Mark D. Rothc5c38782016-09-16 08:51:01 -0700455 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100456 parse_server(server, &addr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700457
458 /* lb token processing */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700459 void *user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700460 if (server->has_load_balance_token) {
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200461 const size_t lb_token_max_length =
462 GPR_ARRAY_SIZE(server->load_balance_token);
463 const size_t lb_token_length =
464 strnlen(server->load_balance_token, lb_token_max_length);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800465 grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
466 server->load_balance_token, lb_token_length);
467 user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
468 lb_token_mdstr)
469 .payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700470 } else {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800471 char *uri = grpc_sockaddr_to_uri(&addr);
472 gpr_log(GPR_INFO,
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700473 "Missing LB token for backend address '%s'. The empty token will "
474 "be used instead",
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800475 uri);
476 gpr_free(uri);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800477 user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700478 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700479
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700480 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
481 false /* is_balancer */,
Mark D. Rothc5c38782016-09-16 08:51:01 -0700482 NULL /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700483 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700484 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700485 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700486 return lb_addresses;
487}
488
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800489/* returns true if the new RR policy should replace the current one, if any */
490static bool update_lb_connectivity_status_locked(
491 grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
492 grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
493 grpc_error *curr_state_error;
494 const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check(
495 &glb_policy->state_tracker, &curr_state_error);
496
497 /* The new connectivity status is a function of the previous one and the new
498 * input coming from the status of the RR policy.
499 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800500 * current state (grpclb's)
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800501 * |
502 * v || I | C | R | TF | SD | <- new state (RR's)
503 * ===++====+=====+=====+======+======+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800504 * I || I | C | R | [I] | [I] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800505 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800506 * C || I | C | R | [C] | [C] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800507 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800508 * R || I | C | R | [R] | [R] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800509 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800510 * TF || I | C | R | [TF] | [TF] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800511 * ---++----+-----+-----+------+------+
512 * SD || NA | NA | NA | NA | NA | (*)
513 * ---++----+-----+-----+------+------+
514 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800515 * A [STATE] indicates that the old RR policy is kept. In those cases, STATE
516 * is the current state of grpclb, which is left untouched.
517 *
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800518 * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
519 * the previous RR instance.
520 *
521 * Note that the status is never updated to SHUTDOWN as a result of calling
522 * this function. Only glb_shutdown() has the power to set that state.
523 *
524 * (*) This function mustn't be called during shutting down. */
525 GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
526
527 switch (new_rr_state) {
528 case GRPC_CHANNEL_TRANSIENT_FAILURE:
529 case GRPC_CHANNEL_SHUTDOWN:
530 GPR_ASSERT(new_rr_state_error != GRPC_ERROR_NONE);
531 return false; /* don't replace the RR policy */
532 case GRPC_CHANNEL_INIT:
533 case GRPC_CHANNEL_IDLE:
534 case GRPC_CHANNEL_CONNECTING:
535 case GRPC_CHANNEL_READY:
536 GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE);
537 }
538
539 if (grpc_lb_glb_trace) {
540 gpr_log(GPR_INFO,
541 "Setting grpclb's state to %s from new RR policy %p state.",
542 grpc_connectivity_state_name(new_rr_state),
543 (void *)glb_policy->rr_policy);
544 }
545 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
546 new_rr_state, GRPC_ERROR_REF(new_rr_state_error),
547 "update_lb_connectivity_status_locked");
548 return true;
549}
550
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700551/* perform a pick over \a rr_policy. Given that a pick can return immediately
552 * (ignoring its completion callback) we need to perform the cleanups this
553 * callback would be otherwise resposible for */
David Garcia Quintas20359062016-10-15 15:22:51 -0700554static bool pick_from_internal_rr_locked(
555 grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy,
556 const grpc_lb_policy_pick_args *pick_args,
557 grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
558 GPR_ASSERT(rr_policy != NULL);
559 const bool pick_done =
560 grpc_lb_policy_pick(exec_ctx, rr_policy, pick_args, target,
561 (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
562 if (pick_done) {
563 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
564 if (grpc_lb_glb_trace) {
565 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
566 (intptr_t)wc_arg->rr_policy);
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700567 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200568 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700569
David Garcia Quintas20359062016-10-15 15:22:51 -0700570 /* add the load reporting initial metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800571 initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
David Garcia Quintas20359062016-10-15 15:22:51 -0700572 pick_args->lb_token_mdelem_storage,
573 GRPC_MDELEM_REF(wc_arg->lb_token));
574
575 gpr_free(wc_arg);
576 }
577 /* else, the pending pick will be registered and taken care of by the
578 * pending pick list inside the RR policy (glb_policy->rr_policy).
579 * Eventually, wrapped_on_complete will be called, which will -among other
580 * things- add the LB token to the call's initial metadata */
David Garcia Quintas20359062016-10-15 15:22:51 -0700581 return pick_done;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700582}
583
David Garcia Quintas90712d52016-10-13 19:33:04 -0700584static grpc_lb_policy *create_rr_locked(
585 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist,
586 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700587 GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700588
589 grpc_lb_policy_args args;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700590 memset(&args, 0, sizeof(args));
David Garcia Quintas65318262016-07-29 13:43:38 -0700591 args.client_channel_factory = glb_policy->cc_factory;
Craig Tillerb28c7e82016-11-18 10:29:04 -0800592 grpc_lb_addresses *addresses =
593 process_serverlist_locked(exec_ctx, serverlist);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700594
595 // Replace the LB addresses in the channel args that we pass down to
596 // the subchannel.
Mark D. Roth557c9902016-10-24 11:12:05 -0700597 static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200598 const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700599 args.args = grpc_channel_args_copy_and_add_and_remove(
600 glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
601 1);
David Garcia Quintas65318262016-07-29 13:43:38 -0700602
603 grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200604 GPR_ASSERT(rr != NULL);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800605 grpc_lb_addresses_destroy(exec_ctx, addresses);
606 grpc_channel_args_destroy(exec_ctx, args.args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700607 return rr;
608}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700609
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200610static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
611 grpc_error *error);
612/* glb_policy->rr_policy may be NULL (initial handover) */
David Garcia Quintas90712d52016-10-13 19:33:04 -0700613static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800614 glb_lb_policy *glb_policy) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700615 GPR_ASSERT(glb_policy->serverlist != NULL &&
616 glb_policy->serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700617
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800618 if (glb_policy->shutting_down) return;
619
David Garcia Quintas4283a262016-11-18 10:43:56 -0800620 grpc_lb_policy *new_rr_policy =
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200621 create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy);
David Garcia Quintas4283a262016-11-18 10:43:56 -0800622 if (new_rr_policy == NULL) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800623 gpr_log(GPR_ERROR,
624 "Failure creating a RoundRobin policy for serverlist update with "
625 "%lu entries. The previous RR instance (%p), if any, will continue "
626 "to be used. Future updates from the LB will attempt to create new "
627 "instances.",
628 (unsigned long)glb_policy->serverlist->num_servers,
David Garcia Quintas4283a262016-11-18 10:43:56 -0800629 (void *)glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800630 return;
David Garcia Quintas65318262016-07-29 13:43:38 -0700631 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200632
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800633 grpc_error *new_rr_state_error = NULL;
634 const grpc_connectivity_state new_rr_state =
David Garcia Quintas4283a262016-11-18 10:43:56 -0800635 grpc_lb_policy_check_connectivity(exec_ctx, new_rr_policy,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800636 &new_rr_state_error);
637 /* Connectivity state is a function of the new RR policy just created */
638 const bool replace_old_rr = update_lb_connectivity_status_locked(
639 exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
640
641 if (!replace_old_rr) {
642 /* dispose of the new RR policy that won't be used after all */
David Garcia Quintas4283a262016-11-18 10:43:56 -0800643 GRPC_LB_POLICY_UNREF(exec_ctx, new_rr_policy, "rr_handover_no_replace");
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800644 if (grpc_lb_glb_trace) {
645 gpr_log(GPR_INFO,
646 "Keeping old RR policy (%p) despite new serverlist: new RR "
647 "policy was in %s connectivity state.",
David Garcia Quintas4283a262016-11-18 10:43:56 -0800648 (void *)glb_policy->rr_policy,
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800649 grpc_connectivity_state_name(new_rr_state));
650 }
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800651 return;
652 }
653
654 if (grpc_lb_glb_trace) {
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800655 gpr_log(GPR_INFO, "Created RR policy (%p) to replace old RR (%p)",
David Garcia Quintas4283a262016-11-18 10:43:56 -0800656 (void *)new_rr_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800657 }
658
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700659 if (glb_policy->rr_policy != NULL) {
David Garcia Quintas41bef452016-07-28 19:19:58 -0700660 /* if we are phasing out an existing RR instance, unref it. */
David Garcia Quintas65318262016-07-29 13:43:38 -0700661 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "rr_handover");
662 }
663
David Garcia Quintas4283a262016-11-18 10:43:56 -0800664 /* Finally update the RR policy to the newly created one */
665 glb_policy->rr_policy = new_rr_policy;
David Garcia Quintas65318262016-07-29 13:43:38 -0700666
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800667 /* Add the gRPC LB's interested_parties pollset_set to that of the newly
668 * created RR policy. This will make the RR policy progress upon activity on
669 * gRPC LB, which in turn is tied to the application's call */
Yuchen Zengb4291642016-09-01 19:17:14 -0700670 grpc_pollset_set_add_pollset_set(exec_ctx,
671 glb_policy->rr_policy->interested_parties,
672 glb_policy->base.interested_parties);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200673
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800674 /* Allocate the data for the tracking of the new RR policy's connectivity.
675 * It'll be deallocated in glb_rr_connectivity_changed() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200676 rr_connectivity_data *rr_connectivity =
677 gpr_malloc(sizeof(rr_connectivity_data));
678 memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
679 grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
Craig Tiller91031da2016-12-28 15:44:25 -0800680 rr_connectivity, grpc_schedule_on_exec_ctx);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200681 rr_connectivity->glb_policy = glb_policy;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800682 rr_connectivity->state = new_rr_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200683
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800684 /* Subscribe to changes to the connectivity of the new RR */
David Garcia Quintase224a762016-11-01 13:00:58 -0700685 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200686 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
687 &rr_connectivity->state,
688 &rr_connectivity->on_change);
David Garcia Quintas65318262016-07-29 13:43:38 -0700689 grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
690
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800691 /* Update picks and pings in wait */
David Garcia Quintas65318262016-07-29 13:43:38 -0700692 pending_pick *pp;
693 while ((pp = glb_policy->pending_picks)) {
694 glb_policy->pending_picks = pp->next;
695 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
696 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
697 if (grpc_lb_glb_trace) {
698 gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
699 (intptr_t)glb_policy->rr_policy);
700 }
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700701 pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
702 &pp->pick_args, pp->target,
703 &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700704 }
705
706 pending_ping *pping;
707 while ((pping = glb_policy->pending_pings)) {
708 glb_policy->pending_pings = pping->next;
709 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
710 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
711 if (grpc_lb_glb_trace) {
712 gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
713 (intptr_t)glb_policy->rr_policy);
714 }
715 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700716 &pping->wrapped_notify_arg.wrapper_closure);
David Garcia Quintas65318262016-07-29 13:43:38 -0700717 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700718}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700719
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700720static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
721 grpc_error *error) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800722 rr_connectivity_data *rr_connectivity = arg;
723 glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700724
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800725 gpr_mu_lock(&glb_policy->mu);
726 const bool shutting_down = glb_policy->shutting_down;
David Garcia Quintas4283a262016-11-18 10:43:56 -0800727 bool unref_needed = false;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800728 GRPC_ERROR_REF(error);
729
730 if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) {
731 /* RR policy shutting down. Don't renew subscription and free the arg of
732 * this callback. In addition we need to stash away the current policy to
733 * be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last
734 * one, the policy would be destroyed, alongside the lock, which would
735 * result in a use-after-free */
David Garcia Quintas4283a262016-11-18 10:43:56 -0800736 unref_needed = true;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800737 gpr_free(rr_connectivity);
738 } else { /* rr state != SHUTDOWN && !shutting down: biz as usual */
739 update_lb_connectivity_status_locked(exec_ctx, glb_policy,
740 rr_connectivity->state, error);
741 /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200742 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800743 &rr_connectivity->state,
744 &rr_connectivity->on_change);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700745 }
David Garcia Quintasf9532952016-11-08 14:14:25 -0800746 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas4283a262016-11-18 10:43:56 -0800747 if (unref_needed) {
748 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
749 "rr_connectivity_cb");
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800750 }
751 GRPC_ERROR_UNREF(error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700752}
753
David Garcia Quintas65318262016-07-29 13:43:38 -0700754static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
755 grpc_lb_policy_factory *factory,
756 grpc_lb_policy_args *args) {
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700757 /* Count the number of gRPC-LB addresses. There must be at least one.
758 * TODO(roth): For now, we ignore non-balancer addresses, but in the
759 * future, we may change the behavior such that we fall back to using
760 * the non-balancer addresses if we cannot reach any balancers. At that
761 * time, this should be changed to allow a list with no balancer addresses,
762 * since the resolver might fail to return a balancer address even when
763 * this is the right LB policy to use. */
Mark D. Roth201db7d2016-12-12 09:36:02 -0800764 const grpc_arg *arg =
765 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700766 GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700767 grpc_lb_addresses *addresses = arg->value.pointer.p;
Mark D. Rothf655c852016-09-06 10:40:38 -0700768 size_t num_grpclb_addrs = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700769 for (size_t i = 0; i < addresses->num_addresses; ++i) {
770 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
Mark D. Rothf655c852016-09-06 10:40:38 -0700771 }
772 if (num_grpclb_addrs == 0) return NULL;
773
David Garcia Quintas65318262016-07-29 13:43:38 -0700774 glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
775 memset(glb_policy, 0, sizeof(*glb_policy));
776
Mark D. Roth201db7d2016-12-12 09:36:02 -0800777 /* Get server name. */
778 arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
779 GPR_ASSERT(arg != NULL);
780 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
David Garcia Quintas855a1062016-12-16 13:11:49 -0800781 grpc_uri *uri = grpc_uri_parse(arg->value.string, true);
782 GPR_ASSERT(uri->path[0] != '\0');
783 glb_policy->server_name =
784 gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
785 if (grpc_lb_glb_trace) {
786 gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.",
787 glb_policy->server_name);
788 }
Mark D. Roth201db7d2016-12-12 09:36:02 -0800789 grpc_uri_destroy(uri);
790
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700791 /* All input addresses in addresses come from a resolver that claims
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700792 * they are LB services. It's the resolver's responsibility to make sure
Mark D. Roth201db7d2016-12-12 09:36:02 -0800793 * this policy is only instantiated and used in that case.
David Garcia Quintas65318262016-07-29 13:43:38 -0700794 *
795 * Create a client channel over them to communicate with a LB service */
796 glb_policy->cc_factory = args->client_channel_factory;
Mark D. Roth98abfd32016-10-21 08:10:51 -0700797 glb_policy->args = grpc_channel_args_copy(args->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700798 GPR_ASSERT(glb_policy->cc_factory != NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700799
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700800 /* construct a target from the addresses in args, given in the form
David Garcia Quintas65318262016-07-29 13:43:38 -0700801 * ipvX://ip1:port1,ip2:port2,...
802 * TODO(dgq): support mixed ip version */
Mark D. Rothf655c852016-09-06 10:40:38 -0700803 char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700804 size_t addr_index = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700805 for (size_t i = 0; i < addresses->num_addresses; i++) {
806 if (addresses->addresses[i].user_data != NULL) {
David Garcia Quintas5ebb7af2016-09-15 10:02:16 -0700807 gpr_log(GPR_ERROR,
808 "This LB policy doesn't support user data. It will be ignored");
809 }
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700810 if (addresses->addresses[i].is_balancer) {
Mark D. Rothc5c38782016-09-16 08:51:01 -0700811 if (addr_index == 0) {
murgatroid99dedb9232016-09-26 13:54:04 -0700812 addr_strs[addr_index++] =
Mark D. Rothfb809b72016-10-26 09:12:25 -0700813 grpc_sockaddr_to_uri(&addresses->addresses[i].address);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700814 } else {
Mark D. Roth49f89f02016-10-26 11:16:59 -0700815 GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
816 &addresses->addresses[i].address,
817 true) > 0);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700818 }
Mark D. Rothf655c852016-09-06 10:40:38 -0700819 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700820 }
821 size_t uri_path_len;
Mark D. Roth989cdcd2016-09-06 13:28:28 -0700822 char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
823 num_grpclb_addrs, ",", &uri_path_len);
David Garcia Quintas65318262016-07-29 13:43:38 -0700824
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700825 /* Create a channel to talk to the LBs.
826 *
827 * We strip out the channel arg for the LB policy name, since we want
828 * to use the default (pick_first) in this case.
829 *
830 * We also strip out the channel arg for the resolved addresses, since
831 * that will be generated by the name resolver used in the LB channel.
832 * Note that the LB channel will use the sockaddr resolver, so this
833 * won't actually generate a query to DNS (or some other name service).
834 * However, the addresses returned by the sockaddr resolver will have
835 * is_balancer=false, whereas our own addresses have is_balancer=true.
836 * We need the LB channel to return addresses with is_balancer=false
837 * so that it does not wind up recursively using the grpclb LB policy,
838 * as per the special case logic in client_channel.c.
Mark D. Rothf75d2692016-12-12 08:41:42 -0800839 *
840 * Finally, we also strip out the channel arg for the server URI,
841 * since that will be different for the LB channel than for the parent
842 * channel. (The client channel factory will re-add this arg with
843 * the right value.)
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700844 */
Mark D. Roth201db7d2016-12-12 09:36:02 -0800845 static const char *keys_to_remove[] = {
846 GRPC_ARG_LB_POLICY_NAME, GRPC_ARG_LB_ADDRESSES, GRPC_ARG_SERVER_URI};
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700847 grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
848 args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
David Garcia Quintas65318262016-07-29 13:43:38 -0700849 glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
850 exec_ctx, glb_policy->cc_factory, target_uri_str,
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700851 GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800852 grpc_channel_args_destroy(exec_ctx, new_args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700853
854 gpr_free(target_uri_str);
Mark D. Rothf655c852016-09-06 10:40:38 -0700855 for (size_t i = 0; i < num_grpclb_addrs; i++) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700856 gpr_free(addr_strs[i]);
857 }
858 gpr_free(addr_strs);
859
860 if (glb_policy->lb_channel == NULL) {
861 gpr_free(glb_policy);
862 return NULL;
863 }
864
David Garcia Quintas65318262016-07-29 13:43:38 -0700865 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
866 gpr_mu_init(&glb_policy->mu);
867 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
868 "grpclb");
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200869
David Garcia Quintas65318262016-07-29 13:43:38 -0700870 return &glb_policy->base;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700871}
872
David Garcia Quintas65318262016-07-29 13:43:38 -0700873static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
874 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
875 GPR_ASSERT(glb_policy->pending_picks == NULL);
876 GPR_ASSERT(glb_policy->pending_pings == NULL);
Mark D. Rothd1604af2016-09-22 11:20:27 -0700877 gpr_free((void *)glb_policy->server_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800878 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700879 grpc_channel_destroy(glb_policy->lb_channel);
880 glb_policy->lb_channel = NULL;
881 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
882 if (glb_policy->serverlist != NULL) {
883 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
884 }
885 gpr_mu_destroy(&glb_policy->mu);
886 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700887}
888
David Garcia Quintas65318262016-07-29 13:43:38 -0700889static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
890 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
891 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200892 glb_policy->shutting_down = true;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700893
David Garcia Quintas65318262016-07-29 13:43:38 -0700894 pending_pick *pp = glb_policy->pending_picks;
895 glb_policy->pending_picks = NULL;
896 pending_ping *pping = glb_policy->pending_pings;
897 glb_policy->pending_pings = NULL;
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800898 if (glb_policy->rr_policy) {
899 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
900 }
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800901 grpc_connectivity_state_set(
902 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
903 GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown");
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800904 /* We need a copy of the lb_call pointer because we can't cancell the call
905 * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
906 * the cancel, needs to acquire that same lock */
907 grpc_call *lb_call = glb_policy->lb_call;
David Garcia Quintas65318262016-07-29 13:43:38 -0700908 gpr_mu_unlock(&glb_policy->mu);
909
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800910 /* glb_policy->lb_call and this local lb_call must be consistent at this point
911 * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
912 * of query_for_backends_locked, which can only be invoked while
913 * glb_policy->shutting_down is false. */
914 if (lb_call != NULL) {
915 grpc_call_cancel(lb_call, NULL);
916 /* lb_on_server_status_received will pick up the cancel and clean up */
917 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700918 while (pp != NULL) {
919 pending_pick *next = pp->next;
920 *pp->target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800921 grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
922 GRPC_ERROR_NONE);
David Garcia Quintas65318262016-07-29 13:43:38 -0700923 pp = next;
924 }
925
926 while (pping != NULL) {
927 pending_ping *next = pping->next;
Craig Tiller91031da2016-12-28 15:44:25 -0800928 grpc_closure_sched(exec_ctx, &pping->wrapped_notify_arg.wrapper_closure,
929 GRPC_ERROR_NONE);
David Garcia Quintas65318262016-07-29 13:43:38 -0700930 pping = next;
931 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700932}
933
934static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
Mark D. Roth5f844002016-09-08 08:20:53 -0700935 grpc_connected_subchannel **target,
936 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700937 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
938 gpr_mu_lock(&glb_policy->mu);
939 pending_pick *pp = glb_policy->pending_picks;
940 glb_policy->pending_picks = NULL;
941 while (pp != NULL) {
942 pending_pick *next = pp->next;
943 if (pp->target == target) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700944 *target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800945 grpc_closure_sched(
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700946 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800947 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -0700948 } else {
949 pp->next = glb_policy->pending_picks;
950 glb_policy->pending_picks = pp;
951 }
952 pp = next;
953 }
954 gpr_mu_unlock(&glb_policy->mu);
Mark D. Roth5f844002016-09-08 08:20:53 -0700955 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700956}
957
David Garcia Quintas65318262016-07-29 13:43:38 -0700958static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
959 uint32_t initial_metadata_flags_mask,
Mark D. Rothe65ff112016-09-09 13:48:38 -0700960 uint32_t initial_metadata_flags_eq,
961 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700962 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
963 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas65318262016-07-29 13:43:38 -0700964 pending_pick *pp = glb_policy->pending_picks;
965 glb_policy->pending_picks = NULL;
966 while (pp != NULL) {
967 pending_pick *next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700968 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -0700969 initial_metadata_flags_eq) {
Craig Tiller91031da2016-12-28 15:44:25 -0800970 grpc_closure_sched(
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700971 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800972 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -0700973 } else {
974 pp->next = glb_policy->pending_picks;
975 glb_policy->pending_picks = pp;
976 }
977 pp = next;
978 }
979 gpr_mu_unlock(&glb_policy->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700980 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700981}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700982
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200983static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
984 glb_lb_policy *glb_policy);
985static void start_picking_locked(grpc_exec_ctx *exec_ctx,
986 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700987 glb_policy->started_picking = true;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200988 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
989 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700990}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700991
David Garcia Quintas65318262016-07-29 13:43:38 -0700992static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
993 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
994 gpr_mu_lock(&glb_policy->mu);
995 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200996 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700997 }
998 gpr_mu_unlock(&glb_policy->mu);
999}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001000
David Garcia Quintas65318262016-07-29 13:43:38 -07001001static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
David Garcia Quintas8aace512016-08-15 14:55:12 -07001002 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas331b9c02016-09-12 18:37:05 -07001003 grpc_connected_subchannel **target, void **user_data,
David Garcia Quintas65318262016-07-29 13:43:38 -07001004 grpc_closure *on_complete) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001005 if (pick_args->lb_token_mdelem_storage == NULL) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001006 *target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -08001007 grpc_closure_sched(
David Garcia Quintas6cc44fc2016-09-12 23:04:35 -07001008 exec_ctx, on_complete,
1009 GRPC_ERROR_CREATE("No mdelem storage for the LB token. Load reporting "
Craig Tiller91031da2016-12-28 15:44:25 -08001010 "won't work without it. Failing"));
Mark D. Roth1e5f6af2016-10-07 08:32:58 -07001011 return 0;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001012 }
1013
David Garcia Quintas65318262016-07-29 13:43:38 -07001014 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1015 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas5cf3c372016-10-03 14:30:03 -07001016 glb_policy->deadline = pick_args->deadline;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001017 bool pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001018
1019 if (glb_policy->rr_policy != NULL) {
1020 if (grpc_lb_glb_trace) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001021 gpr_log(GPR_INFO, "grpclb %p about to PICK from RR %p",
1022 (void *)glb_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001023 }
1024 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
David Garcia Quintas8aace512016-08-15 14:55:12 -07001025
David Garcia Quintas97ba6422016-10-14 13:06:45 -07001026 wrapped_rr_closure_arg *wc_arg = gpr_malloc(sizeof(wrapped_rr_closure_arg));
David Garcia Quintas90712d52016-10-13 19:33:04 -07001027 memset(wc_arg, 0, sizeof(wrapped_rr_closure_arg));
David Garcia Quintas331b9c02016-09-12 18:37:05 -07001028
Craig Tiller91031da2016-12-28 15:44:25 -08001029 grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
1030 grpc_schedule_on_exec_ctx);
David Garcia Quintas90712d52016-10-13 19:33:04 -07001031 wc_arg->rr_policy = glb_policy->rr_policy;
1032 wc_arg->target = target;
1033 wc_arg->wrapped_closure = on_complete;
1034 wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
1035 wc_arg->initial_metadata = pick_args->initial_metadata;
David Garcia Quintas97ba6422016-10-14 13:06:45 -07001036 wc_arg->free_when_done = wc_arg;
David Garcia Quintas58c18e72016-10-14 15:23:45 -07001037 pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas20359062016-10-15 15:22:51 -07001038 pick_args, target, wc_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -07001039 } else {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001040 if (grpc_lb_glb_trace) {
1041 gpr_log(GPR_DEBUG,
1042 "No RR policy in grpclb instance %p. Adding to grpclb's pending "
1043 "picks",
1044 (void *)(glb_policy));
1045 }
David Garcia Quintas8aace512016-08-15 14:55:12 -07001046 add_pending_pick(&glb_policy->pending_picks, pick_args, target,
1047 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -07001048
1049 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001050 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001051 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001052 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001053 }
1054 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001055 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001056}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001057
David Garcia Quintas65318262016-07-29 13:43:38 -07001058static grpc_connectivity_state glb_check_connectivity(
1059 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1060 grpc_error **connectivity_error) {
1061 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1062 grpc_connectivity_state st;
1063 gpr_mu_lock(&glb_policy->mu);
1064 st = grpc_connectivity_state_check(&glb_policy->state_tracker,
1065 connectivity_error);
1066 gpr_mu_unlock(&glb_policy->mu);
1067 return st;
1068}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001069
David Garcia Quintas65318262016-07-29 13:43:38 -07001070static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1071 grpc_closure *closure) {
1072 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1073 gpr_mu_lock(&glb_policy->mu);
1074 if (glb_policy->rr_policy) {
1075 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
1076 } else {
1077 add_pending_ping(&glb_policy->pending_pings, closure);
1078 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001079 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001080 }
1081 }
1082 gpr_mu_unlock(&glb_policy->mu);
1083}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001084
David Garcia Quintas65318262016-07-29 13:43:38 -07001085static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
1086 grpc_lb_policy *pol,
1087 grpc_connectivity_state *current,
1088 grpc_closure *notify) {
1089 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1090 gpr_mu_lock(&glb_policy->mu);
1091 grpc_connectivity_state_notify_on_state_change(
1092 exec_ctx, &glb_policy->state_tracker, current, notify);
1093
1094 gpr_mu_unlock(&glb_policy->mu);
1095}
1096
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001097static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
1098 grpc_error *error);
1099static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
1100 grpc_error *error);
Craig Tillerc5866662016-11-16 15:25:00 -08001101static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
1102 glb_lb_policy *glb_policy) {
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001103 GPR_ASSERT(glb_policy->server_name != NULL);
1104 GPR_ASSERT(glb_policy->server_name[0] != '\0');
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001105 GPR_ASSERT(!glb_policy->shutting_down);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001106
David Garcia Quintas15eba132016-08-09 15:20:48 -07001107 /* Note the following LB call progresses every time there's activity in \a
1108 * glb_policy->base.interested_parties, which is comprised of the polling
Yuchen Zengf7c45ae2016-09-15 13:40:32 -07001109 * entities from \a client_channel. */
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001110 grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001111 glb_policy->lb_call = grpc_channel_create_pollset_set_call(
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001112 exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -07001113 glb_policy->base.interested_parties,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001114 GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
1115 &host, glb_policy->deadline, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -07001116
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001117 grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
1118 grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001119
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001120 grpc_grpclb_request *request =
1121 grpc_grpclb_request_create(glb_policy->server_name);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001122 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001123 glb_policy->lb_request_payload =
David Garcia Quintas65318262016-07-29 13:43:38 -07001124 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001125 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
David Garcia Quintas65318262016-07-29 13:43:38 -07001126 grpc_grpclb_request_destroy(request);
1127
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001128 grpc_closure_init(&glb_policy->lb_on_server_status_received,
Craig Tiller91031da2016-12-28 15:44:25 -08001129 lb_on_server_status_received, glb_policy,
1130 grpc_schedule_on_exec_ctx);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001131 grpc_closure_init(&glb_policy->lb_on_response_received,
Craig Tiller91031da2016-12-28 15:44:25 -08001132 lb_on_response_received, glb_policy,
1133 grpc_schedule_on_exec_ctx);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001134
David Garcia Quintas1edfb952016-11-22 17:15:34 -08001135 gpr_backoff_init(&glb_policy->lb_call_backoff_state,
1136 GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS,
1137 GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER,
1138 GRPC_GRPCLB_RECONNECT_JITTER,
1139 GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000,
1140 GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
David Garcia Quintas65318262016-07-29 13:43:38 -07001141}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001142
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001143static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx,
1144 glb_lb_policy *glb_policy) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001145 GPR_ASSERT(glb_policy->lb_call != NULL);
1146 grpc_call_destroy(glb_policy->lb_call);
1147 glb_policy->lb_call = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -07001148
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001149 grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
1150 grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001151
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001152 grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001153 grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
David Garcia Quintas65318262016-07-29 13:43:38 -07001154}
1155
David Garcia Quintas8d489112016-07-29 15:20:42 -07001156/*
1157 * Auxiliary functions and LB client callbacks.
1158 */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001159static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
1160 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001161 GPR_ASSERT(glb_policy->lb_channel != NULL);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001162 if (glb_policy->shutting_down) return;
1163
Craig Tillerc5866662016-11-16 15:25:00 -08001164 lb_call_init_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001165
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001166 if (grpc_lb_glb_trace) {
1167 gpr_log(GPR_INFO, "Query for backends (grpclb: %p, lb_call: %p)",
1168 (void *)glb_policy, (void *)glb_policy->lb_call);
1169 }
1170 GPR_ASSERT(glb_policy->lb_call != NULL);
1171
David Garcia Quintas65318262016-07-29 13:43:38 -07001172 grpc_call_error call_error;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001173 grpc_op ops[4];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001174 memset(ops, 0, sizeof(ops));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001175
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001176 grpc_op *op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -07001177 op->op = GRPC_OP_SEND_INITIAL_METADATA;
1178 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001179 op->flags = 0;
1180 op->reserved = NULL;
1181 op++;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001182
1183 op->op = GRPC_OP_RECV_INITIAL_METADATA;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001184 op->data.recv_initial_metadata = &glb_policy->lb_initial_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001185 op->flags = 0;
1186 op->reserved = NULL;
1187 op++;
1188
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001189 GPR_ASSERT(glb_policy->lb_request_payload != NULL);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001190 op->op = GRPC_OP_SEND_MESSAGE;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001191 op->data.send_message = glb_policy->lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001192 op->flags = 0;
1193 op->reserved = NULL;
1194 op++;
1195
1196 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1197 op->data.recv_status_on_client.trailing_metadata =
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001198 &glb_policy->lb_trailing_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001199 op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
1200 op->data.recv_status_on_client.status_details =
1201 &glb_policy->lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001202 op->flags = 0;
1203 op->reserved = NULL;
1204 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001205 /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
1206 * count goes to zero) to be unref'd in lb_on_server_status_received */
1207 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received");
David Garcia Quintas65318262016-07-29 13:43:38 -07001208 call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001209 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1210 &glb_policy->lb_on_server_status_received);
David Garcia Quintas65318262016-07-29 13:43:38 -07001211 GPR_ASSERT(GRPC_CALL_OK == call_error);
1212
1213 op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001214 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001215 op->data.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001216 op->flags = 0;
1217 op->reserved = NULL;
1218 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001219 /* take another weak ref to be unref'd in lb_on_response_received */
1220 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received");
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001221 call_error = grpc_call_start_batch_and_execute(
1222 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1223 &glb_policy->lb_on_response_received);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001224 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001225}
1226
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001227static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
1228 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001229 glb_lb_policy *glb_policy = arg;
1230
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001231 grpc_op ops[2];
1232 memset(ops, 0, sizeof(ops));
1233 grpc_op *op = ops;
David Garcia Quintasf9532952016-11-08 14:14:25 -08001234 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001235 if (glb_policy->lb_response_payload != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001236 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001237 /* Received data from the LB server. Look inside
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001238 * glb_policy->lb_response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001239 grpc_byte_buffer_reader bbr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001240 grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001241 grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001242 grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001243 grpc_grpclb_serverlist *serverlist =
1244 grpc_grpclb_response_parse_serverlist(response_slice);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001245 if (serverlist != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001246 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001247 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001248 if (grpc_lb_glb_trace) {
Jan Tattermusch2b398082016-10-07 14:40:30 +02001249 gpr_log(GPR_INFO, "Serverlist with %lu servers received",
1250 (unsigned long)serverlist->num_servers);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001251 for (size_t i = 0; i < serverlist->num_servers; ++i) {
1252 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001253 parse_server(serverlist->servers[i], &addr);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001254 char *ipport;
1255 grpc_sockaddr_to_string(&ipport, &addr, false);
1256 gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport);
1257 gpr_free(ipport);
1258 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001259 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001260
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001261 /* update serverlist */
1262 if (serverlist->num_servers > 0) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001263 if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001264 if (grpc_lb_glb_trace) {
1265 gpr_log(GPR_INFO,
1266 "Incoming server list identical to current, ignoring.");
1267 }
David Garcia Quintas1ebcaa22016-11-21 21:52:47 -08001268 grpc_grpclb_destroy_serverlist(serverlist);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001269 } else { /* new serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001270 if (glb_policy->serverlist != NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001271 /* dispose of the old serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001272 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001273 }
David Garcia Quintas1ebcaa22016-11-21 21:52:47 -08001274 /* and update the copy in the glb_lb_policy instance. This serverlist
1275 * instance will be destroyed either upon the next update or in
1276 * glb_destroy() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001277 glb_policy->serverlist = serverlist;
1278
David Garcia Quintas149f09d2016-11-17 20:43:10 -08001279 rr_handover_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001280 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001281 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001282 if (grpc_lb_glb_trace) {
1283 gpr_log(GPR_INFO,
1284 "Received empty server list. Picks will stay pending until a "
1285 "response with > 0 servers is received");
1286 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001287 }
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001288 } else { /* serverlist == NULL */
1289 gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.",
Craig Tiller32df4672016-11-04 08:21:56 -07001290 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
Craig Tiller18b4ba32016-11-09 15:23:42 -08001291 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001292 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001293
David Garcia Quintas246c5642016-11-01 11:16:52 -07001294 if (!glb_policy->shutting_down) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001295 /* keep listening for serverlist updates */
1296 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas246c5642016-11-01 11:16:52 -07001297 op->data.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001298 op->flags = 0;
1299 op->reserved = NULL;
1300 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001301 /* reuse the "lb_on_response_received" weak ref taken in
1302 * query_for_backends_locked() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001303 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas246c5642016-11-01 11:16:52 -07001304 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1305 &glb_policy->lb_on_response_received); /* loop */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001306 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001307 }
David Garcia Quintasf9532952016-11-08 14:14:25 -08001308 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintase224a762016-11-01 13:00:58 -07001309 } else { /* empty payload: call cancelled. */
1310 /* dispose of the "lb_on_response_received" weak ref taken in
1311 * query_for_backends_locked() and reused in every reception loop */
David Garcia Quintasd4d2ece2016-11-08 14:38:12 -08001312 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintase224a762016-11-01 13:00:58 -07001313 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1314 "lb_on_response_received_empty_payload");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001315 }
1316}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001317
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001318static void lb_call_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
1319 grpc_error *error) {
1320 glb_lb_policy *glb_policy = arg;
1321 gpr_mu_lock(&glb_policy->mu);
1322
1323 if (!glb_policy->shutting_down) {
1324 if (grpc_lb_glb_trace) {
1325 gpr_log(GPR_INFO, "Restaring call to LB server (grpclb %p)",
1326 (void *)glb_policy);
1327 }
1328 GPR_ASSERT(glb_policy->lb_call == NULL);
1329 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001330 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001331 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001332 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1333 "grpclb_on_retry_timer");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001334}
1335
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001336static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
1337 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001338 glb_lb_policy *glb_policy = arg;
1339 gpr_mu_lock(&glb_policy->mu);
1340
1341 GPR_ASSERT(glb_policy->lb_call != NULL);
1342
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001343 if (grpc_lb_glb_trace) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001344 char *status_details =
1345 grpc_slice_to_c_string(glb_policy->lb_call_status_details);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001346 gpr_log(GPR_DEBUG,
1347 "Status from LB server received. Status = %d, Details = '%s', "
1348 "(call: %p)",
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001349 glb_policy->lb_call_status, status_details,
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001350 (void *)glb_policy->lb_call);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001351 gpr_free(status_details);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001352 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001353
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001354 /* We need to perform cleanups no matter what. */
1355 lb_call_destroy_locked(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001356
1357 if (!glb_policy->shutting_down) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001358 /* if we aren't shutting down, restart the LB client call after some time */
1359 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
1360 gpr_timespec next_try =
1361 gpr_backoff_step(&glb_policy->lb_call_backoff_state, now);
1362 if (grpc_lb_glb_trace) {
1363 gpr_log(GPR_DEBUG, "Connection to LB server lost (grpclb: %p)...",
1364 (void *)glb_policy);
1365 gpr_timespec timeout = gpr_time_sub(next_try, now);
1366 if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) {
1367 gpr_log(GPR_DEBUG, "... retrying in %" PRId64 ".%09d seconds.",
1368 timeout.tv_sec, timeout.tv_nsec);
1369 } else {
1370 gpr_log(GPR_DEBUG, "... retrying immediately.");
1371 }
1372 }
1373 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
Masood Malekghassemib5b43722017-01-05 15:07:26 -08001374 grpc_closure_init(&glb_policy->lb_on_call_retry, lb_call_on_retry_timer,
1375 glb_policy, grpc_schedule_on_exec_ctx);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001376 grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
Masood Malekghassemib5b43722017-01-05 15:07:26 -08001377 &glb_policy->lb_on_call_retry, now);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001378 }
1379 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001380 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1381 "lb_on_server_status_received");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001382}
1383
David Garcia Quintas8d489112016-07-29 15:20:42 -07001384/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001385static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
1386 glb_destroy, glb_shutdown, glb_pick,
1387 glb_cancel_pick, glb_cancel_picks, glb_ping_one,
1388 glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
1389
1390static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
1391
1392static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
1393
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001394static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1395 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1396
1397static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1398
1399grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
1400 return &glb_lb_policy_factory;
1401}
1402
1403/* Plugin registration */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001404void grpc_lb_policy_grpclb_init() {
1405 grpc_register_lb_policy(grpc_glb_lb_factory_create());
1406 grpc_register_tracer("glb", &grpc_lb_glb_trace);
1407}
1408
1409void grpc_lb_policy_grpclb_shutdown() {}