blob: 71c7bd958ee30fe71614954057b87cc249c58e76 [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
Craig Tiller9eb0fde2017-03-31 16:59:30 -0700109#include "src/core/ext/filters/client_channel/client_channel.h"
110#include "src/core/ext/filters/client_channel/client_channel_factory.h"
111#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
112#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
113#include "src/core/ext/filters/client_channel/parse_address.h"
114#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
115#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
116#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h"
Mark D. Roth046cf762016-09-26 11:13:51 -0700117#include "src/core/lib/channel/channel_args.h"
Craig Tiller2400bf52017-02-09 16:25:19 -0800118#include "src/core/lib/iomgr/combiner.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200119#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700120#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200121#include "src/core/lib/iomgr/timer.h"
David Garcia Quintas01291502017-02-07 13:26:41 -0800122#include "src/core/lib/slice/slice_hash_table.h"
Craig Tiller18b4ba32016-11-09 15:23:42 -0800123#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -0700124#include "src/core/lib/slice/slice_string_helpers.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200125#include "src/core/lib/support/backoff.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700126#include "src/core/lib/support/string.h"
127#include "src/core/lib/surface/call.h"
128#include "src/core/lib/surface/channel.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700129#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700130
David Garcia Quintas1edfb952016-11-22 17:15:34 -0800131#define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20
132#define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1
133#define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6
134#define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
135#define GRPC_GRPCLB_RECONNECT_JITTER 0.2
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200136
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700137int grpc_lb_glb_trace = 0;
138
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700139/* add lb_token of selected subchannel (address) to the call's initial
140 * metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800141static grpc_error *initial_metadata_add_lb_token(
142 grpc_exec_ctx *exec_ctx, grpc_metadata_batch *initial_metadata,
143 grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700144 GPR_ASSERT(lb_token_mdelem_storage != NULL);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800145 GPR_ASSERT(!GRPC_MDISNULL(lb_token));
146 return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
147 lb_token_mdelem_storage, lb_token);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700148}
149
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700150typedef struct wrapped_rr_closure_arg {
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700151 /* the closure instance using this struct as argument */
152 grpc_closure wrapper_closure;
153
David Garcia Quintas43339842016-07-18 12:56:09 -0700154 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
155 * calls against the internal RR instance, respectively. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700156 grpc_closure *wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700157
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700158 /* the pick's initial metadata, kept in order to append the LB token for the
159 * pick */
160 grpc_metadata_batch *initial_metadata;
161
162 /* the picked target, used to determine which LB token to add to the pick's
163 * initial metadata */
164 grpc_connected_subchannel **target;
165
166 /* the LB token associated with the pick */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800167 grpc_mdelem lb_token;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700168
169 /* storage for the lb token initial metadata mdelem */
170 grpc_linked_mdelem *lb_token_mdelem_storage;
171
David Garcia Quintas43339842016-07-18 12:56:09 -0700172 /* The RR instance related to the closure */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700173 grpc_lb_policy *rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700174
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700175 /* heap memory to be freed upon closure execution. */
176 void *free_when_done;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700177} wrapped_rr_closure_arg;
178
179/* The \a on_complete closure passed as part of the pick requires keeping a
180 * reference to its associated round robin instance. We wrap this closure in
181 * order to unref the round robin instance upon its invocation */
182static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700183 grpc_error *error) {
David Garcia Quintas43339842016-07-18 12:56:09 -0700184 wrapped_rr_closure_arg *wc_arg = arg;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700185
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200186 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
Craig Tiller91031da2016-12-28 15:44:25 -0800187 grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200188
189 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas6493a732016-11-22 10:25:52 -0800190 /* if *target is NULL, no pick has been made by the RR policy (eg, all
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700191 * addresses failed to connect). There won't be any user_data/token
192 * available */
David Garcia Quintas6493a732016-11-22 10:25:52 -0800193 if (*wc_arg->target != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800194 if (!GRPC_MDISNULL(wc_arg->lb_token)) {
195 initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800196 wc_arg->lb_token_mdelem_storage,
197 GRPC_MDELEM_REF(wc_arg->lb_token));
198 } else {
199 gpr_log(GPR_ERROR,
200 "No LB token for connected subchannel pick %p (from RR "
201 "instance %p).",
202 (void *)*wc_arg->target, (void *)wc_arg->rr_policy);
203 abort();
204 }
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700205 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200206 if (grpc_lb_glb_trace) {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800207 gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200208 }
209 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700210 }
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700211 GPR_ASSERT(wc_arg->free_when_done != NULL);
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700212 gpr_free(wc_arg->free_when_done);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700213}
214
David Garcia Quintasea11d162016-07-14 17:27:28 -0700215/* Linked list of pending pick requests. It stores all information needed to
216 * eventually call (Round Robin's) pick() on them. They mainly stay pending
217 * waiting for the RR policy to be created/updated.
218 *
219 * One particularity is the wrapping of the user-provided \a on_complete closure
220 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
221 * order to correctly unref the RR policy instance upon completion of the pick.
222 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700223typedef struct pending_pick {
224 struct pending_pick *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700225
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700226 /* original pick()'s arguments */
227 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700228
229 /* output argument where to store the pick()ed connected subchannel, or NULL
230 * upon error. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700231 grpc_connected_subchannel **target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700232
David Garcia Quintas43339842016-07-18 12:56:09 -0700233 /* args for wrapped_on_complete */
234 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700235} pending_pick;
236
David Garcia Quintas8aace512016-08-15 14:55:12 -0700237static void add_pending_pick(pending_pick **root,
238 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas65318262016-07-29 13:43:38 -0700239 grpc_connected_subchannel **target,
240 grpc_closure *on_complete) {
Craig Tiller6f417882017-02-16 14:09:39 -0800241 pending_pick *pp = gpr_zalloc(sizeof(*pp));
David Garcia Quintas65318262016-07-29 13:43:38 -0700242 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700243 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700244 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700245 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700246 pp->wrapped_on_complete_arg.target = target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700247 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
248 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
249 pick_args->lb_token_mdelem_storage;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700250 pp->wrapped_on_complete_arg.free_when_done = pp;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700251 grpc_closure_init(&pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800252 wrapped_rr_closure, &pp->wrapped_on_complete_arg,
253 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700254 *root = pp;
255}
256
David Garcia Quintasea11d162016-07-14 17:27:28 -0700257/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700258typedef struct pending_ping {
259 struct pending_ping *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700260
David Garcia Quintas43339842016-07-18 12:56:09 -0700261 /* args for wrapped_notify */
262 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700263} pending_ping;
264
David Garcia Quintas65318262016-07-29 13:43:38 -0700265static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
Craig Tiller6f417882017-02-16 14:09:39 -0800266 pending_ping *pping = gpr_zalloc(sizeof(*pping));
David Garcia Quintas65318262016-07-29 13:43:38 -0700267 pping->wrapped_notify_arg.wrapped_closure = notify;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700268 pping->wrapped_notify_arg.free_when_done = pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700269 pping->next = *root;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700270 grpc_closure_init(&pping->wrapped_notify_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800271 wrapped_rr_closure, &pping->wrapped_notify_arg,
272 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700273 *root = pping;
274}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700275
David Garcia Quintas8d489112016-07-29 15:20:42 -0700276/*
277 * glb_lb_policy
278 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700279typedef struct rr_connectivity_data rr_connectivity_data;
David Garcia Quintas65318262016-07-29 13:43:38 -0700280static const grpc_lb_policy_vtable glb_lb_policy_vtable;
281typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700282 /** base policy: must be first */
283 grpc_lb_policy base;
284
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700285 /** who the client is trying to communicate with */
Mark D. Rothd1604af2016-09-22 11:20:27 -0700286 const char *server_name;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700287 grpc_client_channel_factory *cc_factory;
Mark D. Roth046cf762016-09-26 11:13:51 -0700288 grpc_channel_args *args;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700289
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700290 /** deadline for the LB's call */
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700291 gpr_timespec deadline;
292
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700293 /** for communicating with the LB server */
David Garcia Quintasea11d162016-07-14 17:27:28 -0700294 grpc_channel *lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700295
296 /** the RR policy to use of the backend servers returned by the LB server */
297 grpc_lb_policy *rr_policy;
298
299 bool started_picking;
300
301 /** our connectivity state tracker */
302 grpc_connectivity_state_tracker state_tracker;
303
David Garcia Quintasea11d162016-07-14 17:27:28 -0700304 /** stores the deserialized response from the LB. May be NULL until one such
305 * response has arrived. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700306 grpc_grpclb_serverlist *serverlist;
307
David Garcia Quintasea11d162016-07-14 17:27:28 -0700308 /** list of picks that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700309 pending_pick *pending_picks;
310
David Garcia Quintasea11d162016-07-14 17:27:28 -0700311 /** list of pings that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700312 pending_ping *pending_pings;
313
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200314 bool shutting_down;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700315
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200316 /************************************************************/
317 /* client data associated with the LB server communication */
318 /************************************************************/
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100319 /* Status from the LB server has been received. This signals the end of the LB
320 * call. */
321 grpc_closure lb_on_server_status_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200322
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100323 /* A response from the LB server has been received. Process it */
324 grpc_closure lb_on_response_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200325
Masood Malekghassemib5b43722017-01-05 15:07:26 -0800326 /* LB call retry timer callback. */
327 grpc_closure lb_on_call_retry;
328
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200329 grpc_call *lb_call; /* streaming call to the LB server, */
330
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100331 grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */
332 grpc_metadata_array
333 lb_trailing_metadata_recv; /* trailing MD from LB server */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200334
335 /* what's being sent to the LB server. Note that its value may vary if the LB
336 * server indicates a redirect. */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100337 grpc_byte_buffer *lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200338
David Garcia Quintas246c5642016-11-01 11:16:52 -0700339 /* response the LB server, if any. Processed in lb_on_response_received() */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100340 grpc_byte_buffer *lb_response_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200341
David Garcia Quintas246c5642016-11-01 11:16:52 -0700342 /* call status code and details, set in lb_on_server_status_received() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200343 grpc_status_code lb_call_status;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800344 grpc_slice lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200345
346 /** LB call retry backoff state */
347 gpr_backoff lb_call_backoff_state;
348
349 /** LB call retry timer */
350 grpc_timer lb_call_retry_timer;
David Garcia Quintas65318262016-07-29 13:43:38 -0700351} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700352
David Garcia Quintas65318262016-07-29 13:43:38 -0700353/* Keeps track and reacts to changes in connectivity of the RR instance */
354struct rr_connectivity_data {
355 grpc_closure on_change;
356 grpc_connectivity_state state;
357 glb_lb_policy *glb_policy;
358};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700359
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700360static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
361 bool log) {
362 const grpc_grpclb_ip_address *ip = &server->ip_address;
363 if (server->port >> 16 != 0) {
364 if (log) {
365 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200366 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
367 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700368 }
369 return false;
370 }
371
372 if (ip->size != 4 && ip->size != 16) {
373 if (log) {
374 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200375 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700376 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200377 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700378 }
379 return false;
380 }
381 return true;
382}
383
Mark D. Roth16883a32016-10-21 10:30:58 -0700384/* vtable for LB tokens in grpc_lb_addresses. */
Mark D. Roth557c9902016-10-24 11:12:05 -0700385static void *lb_token_copy(void *token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800386 return token == NULL
387 ? NULL
388 : (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload;
Mark D. Roth16883a32016-10-21 10:30:58 -0700389}
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800390static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800391 if (token != NULL) {
392 GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token});
393 }
Mark D. Roth16883a32016-10-21 10:30:58 -0700394}
Mark D. Roth557c9902016-10-24 11:12:05 -0700395static int lb_token_cmp(void *token1, void *token2) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700396 if (token1 > token2) return 1;
397 if (token1 < token2) return -1;
398 return 0;
399}
400static const grpc_lb_user_data_vtable lb_token_vtable = {
401 lb_token_copy, lb_token_destroy, lb_token_cmp};
402
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100403static void parse_server(const grpc_grpclb_server *server,
404 grpc_resolved_address *addr) {
405 const uint16_t netorder_port = htons((uint16_t)server->port);
406 /* the addresses are given in binary format (a in(6)_addr struct) in
407 * server->ip_address.bytes. */
408 const grpc_grpclb_ip_address *ip = &server->ip_address;
409 memset(addr, 0, sizeof(*addr));
410 if (ip->size == 4) {
411 addr->len = sizeof(struct sockaddr_in);
412 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
413 addr4->sin_family = AF_INET;
414 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
415 addr4->sin_port = netorder_port;
416 } else if (ip->size == 16) {
417 addr->len = sizeof(struct sockaddr_in6);
418 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr->addr;
David Garcia Quintas107ca162016-11-02 18:17:03 -0700419 addr6->sin6_family = AF_INET6;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100420 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
421 addr6->sin6_port = netorder_port;
422 }
423}
424
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700425/* Returns addresses extracted from \a serverlist. */
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800426static grpc_lb_addresses *process_serverlist_locked(
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800427 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700428 size_t num_valid = 0;
429 /* first pass: count how many are valid in order to allocate the necessary
430 * memory in a single block */
431 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700432 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700433 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700434 if (num_valid == 0) return NULL;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700435
Mark D. Roth16883a32016-10-21 10:30:58 -0700436 grpc_lb_addresses *lb_addresses =
437 grpc_lb_addresses_create(num_valid, &lb_token_vtable);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700438
439 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700440 * to the outside world) to be read by the RR policy during its creation.
441 * Given that the validity tests are very cheap, they are performed again
442 * instead of marking the valid ones during the first pass, as this would
443 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700444 size_t addr_idx = 0;
445 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
446 GPR_ASSERT(addr_idx < num_valid);
447 const grpc_grpclb_server *server = serverlist->servers[sl_idx];
448 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700449
450 /* address processing */
Mark D. Rothc5c38782016-09-16 08:51:01 -0700451 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100452 parse_server(server, &addr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700453
454 /* lb token processing */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700455 void *user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700456 if (server->has_load_balance_token) {
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200457 const size_t lb_token_max_length =
458 GPR_ARRAY_SIZE(server->load_balance_token);
459 const size_t lb_token_length =
460 strnlen(server->load_balance_token, lb_token_max_length);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800461 grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
462 server->load_balance_token, lb_token_length);
463 user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
464 lb_token_mdstr)
465 .payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700466 } else {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800467 char *uri = grpc_sockaddr_to_uri(&addr);
468 gpr_log(GPR_INFO,
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700469 "Missing LB token for backend address '%s'. The empty token will "
470 "be used instead",
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800471 uri);
472 gpr_free(uri);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800473 user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700474 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700475
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700476 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
477 false /* is_balancer */,
Mark D. Rothc5c38782016-09-16 08:51:01 -0700478 NULL /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700479 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700480 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700481 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700482 return lb_addresses;
483}
484
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800485/* returns true if the new RR policy should replace the current one, if any */
486static bool update_lb_connectivity_status_locked(
487 grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
488 grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800489 const grpc_connectivity_state curr_glb_state =
490 grpc_connectivity_state_check(&glb_policy->state_tracker);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800491
492 /* The new connectivity status is a function of the previous one and the new
493 * input coming from the status of the RR policy.
494 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800495 * current state (grpclb's)
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800496 * |
497 * v || I | C | R | TF | SD | <- new state (RR's)
498 * ===++====+=====+=====+======+======+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800499 * I || I | C | R | [I] | [I] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800500 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800501 * C || I | C | R | [C] | [C] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800502 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800503 * R || I | C | R | [R] | [R] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800504 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800505 * TF || I | C | R | [TF] | [TF] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800506 * ---++----+-----+-----+------+------+
507 * SD || NA | NA | NA | NA | NA | (*)
508 * ---++----+-----+-----+------+------+
509 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800510 * A [STATE] indicates that the old RR policy is kept. In those cases, STATE
511 * is the current state of grpclb, which is left untouched.
512 *
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800513 * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
514 * the previous RR instance.
515 *
516 * Note that the status is never updated to SHUTDOWN as a result of calling
517 * this function. Only glb_shutdown() has the power to set that state.
518 *
519 * (*) This function mustn't be called during shutting down. */
520 GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
521
522 switch (new_rr_state) {
523 case GRPC_CHANNEL_TRANSIENT_FAILURE:
524 case GRPC_CHANNEL_SHUTDOWN:
525 GPR_ASSERT(new_rr_state_error != GRPC_ERROR_NONE);
526 return false; /* don't replace the RR policy */
527 case GRPC_CHANNEL_INIT:
528 case GRPC_CHANNEL_IDLE:
529 case GRPC_CHANNEL_CONNECTING:
530 case GRPC_CHANNEL_READY:
531 GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE);
532 }
533
534 if (grpc_lb_glb_trace) {
535 gpr_log(GPR_INFO,
536 "Setting grpclb's state to %s from new RR policy %p state.",
537 grpc_connectivity_state_name(new_rr_state),
538 (void *)glb_policy->rr_policy);
539 }
540 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
541 new_rr_state, GRPC_ERROR_REF(new_rr_state_error),
542 "update_lb_connectivity_status_locked");
543 return true;
544}
545
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700546/* perform a pick over \a rr_policy. Given that a pick can return immediately
547 * (ignoring its completion callback) we need to perform the cleanups this
548 * callback would be otherwise resposible for */
David Garcia Quintas20359062016-10-15 15:22:51 -0700549static bool pick_from_internal_rr_locked(
550 grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy,
551 const grpc_lb_policy_pick_args *pick_args,
552 grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
553 GPR_ASSERT(rr_policy != NULL);
Craig Tiller2400bf52017-02-09 16:25:19 -0800554 const bool pick_done = grpc_lb_policy_pick_locked(
555 exec_ctx, rr_policy, pick_args, target, (void **)&wc_arg->lb_token,
556 &wc_arg->wrapper_closure);
David Garcia Quintas20359062016-10-15 15:22:51 -0700557 if (pick_done) {
558 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
559 if (grpc_lb_glb_trace) {
560 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
561 (intptr_t)wc_arg->rr_policy);
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700562 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200563 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700564
David Garcia Quintas20359062016-10-15 15:22:51 -0700565 /* add the load reporting initial metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800566 initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
David Garcia Quintas20359062016-10-15 15:22:51 -0700567 pick_args->lb_token_mdelem_storage,
568 GRPC_MDELEM_REF(wc_arg->lb_token));
569
570 gpr_free(wc_arg);
571 }
572 /* else, the pending pick will be registered and taken care of by the
573 * pending pick list inside the RR policy (glb_policy->rr_policy).
574 * Eventually, wrapped_on_complete will be called, which will -among other
575 * things- add the LB token to the call's initial metadata */
David Garcia Quintas20359062016-10-15 15:22:51 -0700576 return pick_done;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700577}
578
David Garcia Quintas90712d52016-10-13 19:33:04 -0700579static grpc_lb_policy *create_rr_locked(
580 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist,
581 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700582 GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700583
584 grpc_lb_policy_args args;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700585 memset(&args, 0, sizeof(args));
David Garcia Quintas65318262016-07-29 13:43:38 -0700586 args.client_channel_factory = glb_policy->cc_factory;
Craig Tiller46dd7902017-02-23 09:42:16 -0800587 args.combiner = glb_policy->base.combiner;
Craig Tillerb28c7e82016-11-18 10:29:04 -0800588 grpc_lb_addresses *addresses =
589 process_serverlist_locked(exec_ctx, serverlist);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700590
591 // Replace the LB addresses in the channel args that we pass down to
592 // the subchannel.
Mark D. Roth557c9902016-10-24 11:12:05 -0700593 static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200594 const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700595 args.args = grpc_channel_args_copy_and_add_and_remove(
596 glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
597 1);
David Garcia Quintas65318262016-07-29 13:43:38 -0700598
599 grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200600 GPR_ASSERT(rr != NULL);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800601 grpc_lb_addresses_destroy(exec_ctx, addresses);
602 grpc_channel_args_destroy(exec_ctx, args.args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700603 return rr;
604}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700605
Craig Tiller2400bf52017-02-09 16:25:19 -0800606static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx,
607 void *arg, grpc_error *error);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200608/* glb_policy->rr_policy may be NULL (initial handover) */
David Garcia Quintas90712d52016-10-13 19:33:04 -0700609static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800610 glb_lb_policy *glb_policy) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700611 GPR_ASSERT(glb_policy->serverlist != NULL &&
612 glb_policy->serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700613
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800614 if (glb_policy->shutting_down) return;
615
David Garcia Quintas4283a262016-11-18 10:43:56 -0800616 grpc_lb_policy *new_rr_policy =
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200617 create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy);
David Garcia Quintas4283a262016-11-18 10:43:56 -0800618 if (new_rr_policy == NULL) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800619 gpr_log(GPR_ERROR,
620 "Failure creating a RoundRobin policy for serverlist update with "
621 "%lu entries. The previous RR instance (%p), if any, will continue "
622 "to be used. Future updates from the LB will attempt to create new "
623 "instances.",
624 (unsigned long)glb_policy->serverlist->num_servers,
David Garcia Quintas4283a262016-11-18 10:43:56 -0800625 (void *)glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800626 return;
David Garcia Quintas65318262016-07-29 13:43:38 -0700627 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200628
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800629 grpc_error *new_rr_state_error = NULL;
630 const grpc_connectivity_state new_rr_state =
Craig Tiller2400bf52017-02-09 16:25:19 -0800631 grpc_lb_policy_check_connectivity_locked(exec_ctx, new_rr_policy,
632 &new_rr_state_error);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800633 /* Connectivity state is a function of the new RR policy just created */
634 const bool replace_old_rr = update_lb_connectivity_status_locked(
635 exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
636
637 if (!replace_old_rr) {
638 /* dispose of the new RR policy that won't be used after all */
David Garcia Quintas4283a262016-11-18 10:43:56 -0800639 GRPC_LB_POLICY_UNREF(exec_ctx, new_rr_policy, "rr_handover_no_replace");
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800640 if (grpc_lb_glb_trace) {
641 gpr_log(GPR_INFO,
642 "Keeping old RR policy (%p) despite new serverlist: new RR "
643 "policy was in %s connectivity state.",
David Garcia Quintas4283a262016-11-18 10:43:56 -0800644 (void *)glb_policy->rr_policy,
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800645 grpc_connectivity_state_name(new_rr_state));
646 }
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800647 return;
648 }
649
650 if (grpc_lb_glb_trace) {
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800651 gpr_log(GPR_INFO, "Created RR policy (%p) to replace old RR (%p)",
David Garcia Quintas4283a262016-11-18 10:43:56 -0800652 (void *)new_rr_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800653 }
654
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700655 if (glb_policy->rr_policy != NULL) {
David Garcia Quintas41bef452016-07-28 19:19:58 -0700656 /* if we are phasing out an existing RR instance, unref it. */
David Garcia Quintas65318262016-07-29 13:43:38 -0700657 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "rr_handover");
658 }
659
David Garcia Quintas4283a262016-11-18 10:43:56 -0800660 /* Finally update the RR policy to the newly created one */
661 glb_policy->rr_policy = new_rr_policy;
David Garcia Quintas65318262016-07-29 13:43:38 -0700662
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800663 /* Add the gRPC LB's interested_parties pollset_set to that of the newly
664 * created RR policy. This will make the RR policy progress upon activity on
665 * gRPC LB, which in turn is tied to the application's call */
Yuchen Zengb4291642016-09-01 19:17:14 -0700666 grpc_pollset_set_add_pollset_set(exec_ctx,
667 glb_policy->rr_policy->interested_parties,
668 glb_policy->base.interested_parties);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200669
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800670 /* Allocate the data for the tracking of the new RR policy's connectivity.
671 * It'll be deallocated in glb_rr_connectivity_changed() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200672 rr_connectivity_data *rr_connectivity =
Craig Tiller6f417882017-02-16 14:09:39 -0800673 gpr_zalloc(sizeof(rr_connectivity_data));
Craig Tiller2400bf52017-02-09 16:25:19 -0800674 grpc_closure_init(&rr_connectivity->on_change,
675 glb_rr_connectivity_changed_locked, rr_connectivity,
676 grpc_combiner_scheduler(glb_policy->base.combiner, false));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200677 rr_connectivity->glb_policy = glb_policy;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800678 rr_connectivity->state = new_rr_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200679
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800680 /* Subscribe to changes to the connectivity of the new RR */
David Garcia Quintase224a762016-11-01 13:00:58 -0700681 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
Craig Tiller2400bf52017-02-09 16:25:19 -0800682 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
683 &rr_connectivity->state,
684 &rr_connectivity->on_change);
685 grpc_lb_policy_exit_idle_locked(exec_ctx, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700686
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800687 /* Update picks and pings in wait */
David Garcia Quintas65318262016-07-29 13:43:38 -0700688 pending_pick *pp;
689 while ((pp = glb_policy->pending_picks)) {
690 glb_policy->pending_picks = pp->next;
691 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
692 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
693 if (grpc_lb_glb_trace) {
694 gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
695 (intptr_t)glb_policy->rr_policy);
696 }
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700697 pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
698 &pp->pick_args, pp->target,
699 &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700700 }
701
702 pending_ping *pping;
703 while ((pping = glb_policy->pending_pings)) {
704 glb_policy->pending_pings = pping->next;
705 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
706 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
707 if (grpc_lb_glb_trace) {
708 gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
709 (intptr_t)glb_policy->rr_policy);
710 }
Craig Tiller2400bf52017-02-09 16:25:19 -0800711 grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy,
712 &pping->wrapped_notify_arg.wrapper_closure);
David Garcia Quintas65318262016-07-29 13:43:38 -0700713 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700714}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700715
Craig Tiller2400bf52017-02-09 16:25:19 -0800716static void glb_rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx,
717 void *arg, grpc_error *error) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800718 rr_connectivity_data *rr_connectivity = arg;
719 glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700720
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800721 const bool shutting_down = glb_policy->shutting_down;
David Garcia Quintas4283a262016-11-18 10:43:56 -0800722 bool unref_needed = false;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800723 GRPC_ERROR_REF(error);
724
725 if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) {
726 /* RR policy shutting down. Don't renew subscription and free the arg of
727 * this callback. In addition we need to stash away the current policy to
728 * be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last
729 * one, the policy would be destroyed, alongside the lock, which would
730 * result in a use-after-free */
David Garcia Quintas4283a262016-11-18 10:43:56 -0800731 unref_needed = true;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800732 gpr_free(rr_connectivity);
733 } else { /* rr state != SHUTDOWN && !shutting down: biz as usual */
734 update_lb_connectivity_status_locked(exec_ctx, glb_policy,
735 rr_connectivity->state, error);
736 /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
Craig Tiller2400bf52017-02-09 16:25:19 -0800737 grpc_lb_policy_notify_on_state_change_locked(
738 exec_ctx, glb_policy->rr_policy, &rr_connectivity->state,
739 &rr_connectivity->on_change);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700740 }
David Garcia Quintas4283a262016-11-18 10:43:56 -0800741 if (unref_needed) {
742 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
743 "rr_connectivity_cb");
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800744 }
745 GRPC_ERROR_UNREF(error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700746}
747
David Garcia Quintas01291502017-02-07 13:26:41 -0800748static void destroy_balancer_name(grpc_exec_ctx *exec_ctx,
749 void *balancer_name) {
750 gpr_free(balancer_name);
751}
752
753static void *copy_balancer_name(void *balancer_name) {
754 return gpr_strdup(balancer_name);
755}
756
757static grpc_slice_hash_table_entry targets_info_entry_create(
758 const char *address, const char *balancer_name) {
759 static const grpc_slice_hash_table_vtable vtable = {destroy_balancer_name,
760 copy_balancer_name};
761 grpc_slice_hash_table_entry entry;
762 entry.key = grpc_slice_from_copied_string(address);
763 entry.value = (void *)balancer_name;
764 entry.vtable = &vtable;
765 return entry;
766}
767
768/* Returns the target URI for the LB service whose addresses are in \a
769 * addresses. Using this URI, a bidirectional streaming channel will be created
770 * for the reception of load balancing updates.
771 *
772 * The output argument \a targets_info will be updated to contain a mapping of
773 * "LB server address" to "balancer name", as reported by the naming system.
774 * This mapping will be propagated via the channel arguments of the
775 * aforementioned LB streaming channel, to be used by the security connector for
776 * secure naming checks. The user is responsible for freeing \a targets_info. */
777static char *get_lb_uri_target_addresses(grpc_exec_ctx *exec_ctx,
778 const grpc_lb_addresses *addresses,
779 grpc_slice_hash_table **targets_info) {
780 size_t num_grpclb_addrs = 0;
781 for (size_t i = 0; i < addresses->num_addresses; ++i) {
782 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
783 }
784 /* All input addresses come from a resolver that claims they are LB services.
785 * It's the resolver's responsibility to make sure this policy is only
786 * instantiated and used in that case. Otherwise, something has gone wrong. */
787 GPR_ASSERT(num_grpclb_addrs > 0);
788
789 grpc_slice_hash_table_entry *targets_info_entries =
790 gpr_malloc(sizeof(*targets_info_entries) * num_grpclb_addrs);
791
792 /* construct a target ipvX://ip1:port1,ip2:port2,... from the addresses in \a
793 * addresses */
794 /* TODO(dgq): support mixed ip version */
795 char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
796 size_t addr_index = 0;
797
798 for (size_t i = 0; i < addresses->num_addresses; i++) {
799 if (addresses->addresses[i].user_data != NULL) {
800 gpr_log(GPR_ERROR,
801 "This LB policy doesn't support user data. It will be ignored");
802 }
803 if (addresses->addresses[i].is_balancer) {
804 char *addr_str;
805 GPR_ASSERT(grpc_sockaddr_to_string(
806 &addr_str, &addresses->addresses[i].address, true) > 0);
807 targets_info_entries[addr_index] = targets_info_entry_create(
808 addr_str, addresses->addresses[i].balancer_name);
809 addr_strs[addr_index++] = addr_str;
810 }
811 }
812 GPR_ASSERT(addr_index == num_grpclb_addrs);
813
814 size_t uri_path_len;
815 char *uri_path = gpr_strjoin_sep((const char **)addr_strs, num_grpclb_addrs,
816 ",", &uri_path_len);
817 for (size_t i = 0; i < num_grpclb_addrs; i++) gpr_free(addr_strs[i]);
818 gpr_free(addr_strs);
819
820 char *target_uri_str = NULL;
821 /* TODO(dgq): Don't assume all addresses will share the scheme of the first
822 * one */
823 gpr_asprintf(&target_uri_str, "%s:%s",
824 grpc_sockaddr_get_uri_scheme(&addresses->addresses[0].address),
825 uri_path);
826 gpr_free(uri_path);
827
828 *targets_info =
829 grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries);
830 for (size_t i = 0; i < num_grpclb_addrs; i++) {
831 grpc_slice_unref_internal(exec_ctx, targets_info_entries[i].key);
832 }
833 gpr_free(targets_info_entries);
834
835 return target_uri_str;
836}
837
David Garcia Quintas65318262016-07-29 13:43:38 -0700838static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
839 grpc_lb_policy_factory *factory,
840 grpc_lb_policy_args *args) {
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700841 /* Count the number of gRPC-LB addresses. There must be at least one.
842 * TODO(roth): For now, we ignore non-balancer addresses, but in the
843 * future, we may change the behavior such that we fall back to using
844 * the non-balancer addresses if we cannot reach any balancers. At that
845 * time, this should be changed to allow a list with no balancer addresses,
846 * since the resolver might fail to return a balancer address even when
847 * this is the right LB policy to use. */
Mark D. Roth201db7d2016-12-12 09:36:02 -0800848 const grpc_arg *arg =
849 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700850 GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700851 grpc_lb_addresses *addresses = arg->value.pointer.p;
Mark D. Rothf655c852016-09-06 10:40:38 -0700852 size_t num_grpclb_addrs = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700853 for (size_t i = 0; i < addresses->num_addresses; ++i) {
854 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
Mark D. Rothf655c852016-09-06 10:40:38 -0700855 }
856 if (num_grpclb_addrs == 0) return NULL;
857
Craig Tiller6f417882017-02-16 14:09:39 -0800858 glb_lb_policy *glb_policy = gpr_zalloc(sizeof(*glb_policy));
David Garcia Quintas65318262016-07-29 13:43:38 -0700859
Mark D. Roth201db7d2016-12-12 09:36:02 -0800860 /* Get server name. */
861 arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
862 GPR_ASSERT(arg != NULL);
863 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Yuchen Zengc40d1d82017-02-15 20:42:06 -0800864 grpc_uri *uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
David Garcia Quintas855a1062016-12-16 13:11:49 -0800865 GPR_ASSERT(uri->path[0] != '\0');
866 glb_policy->server_name =
867 gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
868 if (grpc_lb_glb_trace) {
869 gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.",
870 glb_policy->server_name);
871 }
Mark D. Roth201db7d2016-12-12 09:36:02 -0800872 grpc_uri_destroy(uri);
873
David Garcia Quintas65318262016-07-29 13:43:38 -0700874 glb_policy->cc_factory = args->client_channel_factory;
Mark D. Roth98abfd32016-10-21 08:10:51 -0700875 glb_policy->args = grpc_channel_args_copy(args->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700876 GPR_ASSERT(glb_policy->cc_factory != NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700877
David Garcia Quintas01291502017-02-07 13:26:41 -0800878 grpc_slice_hash_table *targets_info = NULL;
879 /* Create a client channel over them to communicate with a LB service */
880 char *lb_service_target_addresses =
881 get_lb_uri_target_addresses(exec_ctx, addresses, &targets_info);
882 grpc_channel_args *lb_channel_args =
883 get_lb_channel_args(exec_ctx, targets_info, args->args);
884 glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
885 exec_ctx, lb_service_target_addresses, args->client_channel_factory,
886 lb_channel_args);
887 grpc_slice_hash_table_unref(exec_ctx, targets_info);
888 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
889 gpr_free(lb_service_target_addresses);
David Garcia Quintas65318262016-07-29 13:43:38 -0700890 if (glb_policy->lb_channel == NULL) {
891 gpr_free(glb_policy);
892 return NULL;
893 }
Craig Tiller2400bf52017-02-09 16:25:19 -0800894 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
David Garcia Quintas65318262016-07-29 13:43:38 -0700895 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
896 "grpclb");
897 return &glb_policy->base;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700898}
899
David Garcia Quintas65318262016-07-29 13:43:38 -0700900static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
901 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
902 GPR_ASSERT(glb_policy->pending_picks == NULL);
903 GPR_ASSERT(glb_policy->pending_pings == NULL);
Mark D. Rothd1604af2016-09-22 11:20:27 -0700904 gpr_free((void *)glb_policy->server_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800905 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700906 grpc_channel_destroy(glb_policy->lb_channel);
907 glb_policy->lb_channel = NULL;
908 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
909 if (glb_policy->serverlist != NULL) {
910 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
911 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700912 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700913}
914
Craig Tiller2400bf52017-02-09 16:25:19 -0800915static void glb_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700916 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200917 glb_policy->shutting_down = true;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700918
David Garcia Quintas65318262016-07-29 13:43:38 -0700919 pending_pick *pp = glb_policy->pending_picks;
920 glb_policy->pending_picks = NULL;
921 pending_ping *pping = glb_policy->pending_pings;
922 glb_policy->pending_pings = NULL;
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800923 if (glb_policy->rr_policy) {
924 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
925 }
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800926 grpc_connectivity_state_set(
927 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700928 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "glb_shutdown");
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800929 /* We need a copy of the lb_call pointer because we can't cancell the call
930 * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
931 * the cancel, needs to acquire that same lock */
932 grpc_call *lb_call = glb_policy->lb_call;
David Garcia Quintas65318262016-07-29 13:43:38 -0700933
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800934 /* glb_policy->lb_call and this local lb_call must be consistent at this point
935 * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
936 * of query_for_backends_locked, which can only be invoked while
937 * glb_policy->shutting_down is false. */
938 if (lb_call != NULL) {
939 grpc_call_cancel(lb_call, NULL);
940 /* lb_on_server_status_received will pick up the cancel and clean up */
941 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700942 while (pp != NULL) {
943 pending_pick *next = pp->next;
944 *pp->target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800945 grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
946 GRPC_ERROR_NONE);
David Garcia Quintas65318262016-07-29 13:43:38 -0700947 pp = next;
948 }
949
950 while (pping != NULL) {
951 pending_ping *next = pping->next;
Craig Tiller91031da2016-12-28 15:44:25 -0800952 grpc_closure_sched(exec_ctx, &pping->wrapped_notify_arg.wrapper_closure,
953 GRPC_ERROR_NONE);
David Garcia Quintas65318262016-07-29 13:43:38 -0700954 pping = next;
955 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700956}
957
Craig Tiller2400bf52017-02-09 16:25:19 -0800958static void glb_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
959 grpc_connected_subchannel **target,
960 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700961 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -0700962 pending_pick *pp = glb_policy->pending_picks;
963 glb_policy->pending_picks = NULL;
964 while (pp != NULL) {
965 pending_pick *next = pp->next;
966 if (pp->target == target) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700967 *target = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -0700968 grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
969 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
970 "Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -0700971 } else {
972 pp->next = glb_policy->pending_picks;
973 glb_policy->pending_picks = pp;
974 }
975 pp = next;
976 }
Mark D. Roth5f844002016-09-08 08:20:53 -0700977 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700978}
979
Craig Tiller2400bf52017-02-09 16:25:19 -0800980static void glb_cancel_picks_locked(grpc_exec_ctx *exec_ctx,
981 grpc_lb_policy *pol,
982 uint32_t initial_metadata_flags_mask,
983 uint32_t initial_metadata_flags_eq,
984 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700985 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -0700986 pending_pick *pp = glb_policy->pending_picks;
987 glb_policy->pending_picks = NULL;
988 while (pp != NULL) {
989 pending_pick *next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700990 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -0700991 initial_metadata_flags_eq) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700992 grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
993 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
994 "Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -0700995 } else {
996 pp->next = glb_policy->pending_picks;
997 glb_policy->pending_picks = pp;
998 }
999 pp = next;
1000 }
Mark D. Rothe65ff112016-09-09 13:48:38 -07001001 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001002}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001003
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001004static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
1005 glb_lb_policy *glb_policy);
1006static void start_picking_locked(grpc_exec_ctx *exec_ctx,
1007 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001008 glb_policy->started_picking = true;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001009 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
1010 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001011}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001012
Craig Tiller2400bf52017-02-09 16:25:19 -08001013static void glb_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001014 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001015 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001016 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001017 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001018}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001019
Craig Tiller2400bf52017-02-09 16:25:19 -08001020static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1021 const grpc_lb_policy_pick_args *pick_args,
1022 grpc_connected_subchannel **target, void **user_data,
1023 grpc_closure *on_complete) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001024 if (pick_args->lb_token_mdelem_storage == NULL) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001025 *target = NULL;
ncteisen4b36a3d2017-03-13 19:08:06 -07001026 grpc_closure_sched(exec_ctx, on_complete,
1027 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1028 "No mdelem storage for the LB token. Load reporting "
1029 "won't work without it. Failing"));
Mark D. Roth1e5f6af2016-10-07 08:32:58 -07001030 return 0;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001031 }
1032
David Garcia Quintas65318262016-07-29 13:43:38 -07001033 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas5cf3c372016-10-03 14:30:03 -07001034 glb_policy->deadline = pick_args->deadline;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001035 bool pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001036
1037 if (glb_policy->rr_policy != NULL) {
1038 if (grpc_lb_glb_trace) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001039 gpr_log(GPR_INFO, "grpclb %p about to PICK from RR %p",
1040 (void *)glb_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001041 }
1042 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
David Garcia Quintas8aace512016-08-15 14:55:12 -07001043
Craig Tiller6f417882017-02-16 14:09:39 -08001044 wrapped_rr_closure_arg *wc_arg = gpr_zalloc(sizeof(wrapped_rr_closure_arg));
David Garcia Quintas331b9c02016-09-12 18:37:05 -07001045
Craig Tiller91031da2016-12-28 15:44:25 -08001046 grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
1047 grpc_schedule_on_exec_ctx);
David Garcia Quintas90712d52016-10-13 19:33:04 -07001048 wc_arg->rr_policy = glb_policy->rr_policy;
1049 wc_arg->target = target;
1050 wc_arg->wrapped_closure = on_complete;
1051 wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
1052 wc_arg->initial_metadata = pick_args->initial_metadata;
David Garcia Quintas97ba6422016-10-14 13:06:45 -07001053 wc_arg->free_when_done = wc_arg;
David Garcia Quintas58c18e72016-10-14 15:23:45 -07001054 pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas20359062016-10-15 15:22:51 -07001055 pick_args, target, wc_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -07001056 } else {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001057 if (grpc_lb_glb_trace) {
1058 gpr_log(GPR_DEBUG,
1059 "No RR policy in grpclb instance %p. Adding to grpclb's pending "
1060 "picks",
1061 (void *)(glb_policy));
1062 }
David Garcia Quintas8aace512016-08-15 14:55:12 -07001063 add_pending_pick(&glb_policy->pending_picks, pick_args, target,
1064 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -07001065
1066 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001067 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001068 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001069 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001070 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001071 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001072}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001073
Craig Tiller2400bf52017-02-09 16:25:19 -08001074static grpc_connectivity_state glb_check_connectivity_locked(
David Garcia Quintas65318262016-07-29 13:43:38 -07001075 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1076 grpc_error **connectivity_error) {
1077 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
Craig Tiller2400bf52017-02-09 16:25:19 -08001078 return grpc_connectivity_state_get(&glb_policy->state_tracker,
1079 connectivity_error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001080}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001081
Craig Tiller2400bf52017-02-09 16:25:19 -08001082static void glb_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1083 grpc_closure *closure) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001084 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001085 if (glb_policy->rr_policy) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001086 grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, closure);
David Garcia Quintas65318262016-07-29 13:43:38 -07001087 } else {
1088 add_pending_ping(&glb_policy->pending_pings, closure);
1089 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001090 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001091 }
1092 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001093}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001094
Craig Tiller2400bf52017-02-09 16:25:19 -08001095static void glb_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
1096 grpc_lb_policy *pol,
1097 grpc_connectivity_state *current,
1098 grpc_closure *notify) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001099 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001100 grpc_connectivity_state_notify_on_state_change(
1101 exec_ctx, &glb_policy->state_tracker, current, notify);
David Garcia Quintas65318262016-07-29 13:43:38 -07001102}
1103
Craig Tiller2400bf52017-02-09 16:25:19 -08001104static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx,
1105 void *arg, grpc_error *error);
1106static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
1107 grpc_error *error);
Craig Tillerc5866662016-11-16 15:25:00 -08001108static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
1109 glb_lb_policy *glb_policy) {
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001110 GPR_ASSERT(glb_policy->server_name != NULL);
1111 GPR_ASSERT(glb_policy->server_name[0] != '\0');
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001112 GPR_ASSERT(!glb_policy->shutting_down);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001113
David Garcia Quintas15eba132016-08-09 15:20:48 -07001114 /* Note the following LB call progresses every time there's activity in \a
1115 * glb_policy->base.interested_parties, which is comprised of the polling
Yuchen Zengf7c45ae2016-09-15 13:40:32 -07001116 * entities from \a client_channel. */
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001117 grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001118 glb_policy->lb_call = grpc_channel_create_pollset_set_call(
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001119 exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -07001120 glb_policy->base.interested_parties,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001121 GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
1122 &host, glb_policy->deadline, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -07001123
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001124 grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
1125 grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001126
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001127 grpc_grpclb_request *request =
1128 grpc_grpclb_request_create(glb_policy->server_name);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001129 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001130 glb_policy->lb_request_payload =
David Garcia Quintas65318262016-07-29 13:43:38 -07001131 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001132 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
David Garcia Quintas65318262016-07-29 13:43:38 -07001133 grpc_grpclb_request_destroy(request);
1134
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001135 grpc_closure_init(&glb_policy->lb_on_server_status_received,
Craig Tiller2400bf52017-02-09 16:25:19 -08001136 lb_on_server_status_received_locked, glb_policy,
1137 grpc_combiner_scheduler(glb_policy->base.combiner, false));
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001138 grpc_closure_init(&glb_policy->lb_on_response_received,
Craig Tiller2400bf52017-02-09 16:25:19 -08001139 lb_on_response_received_locked, glb_policy,
1140 grpc_combiner_scheduler(glb_policy->base.combiner, false));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001141
David Garcia Quintas1edfb952016-11-22 17:15:34 -08001142 gpr_backoff_init(&glb_policy->lb_call_backoff_state,
1143 GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS,
1144 GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER,
1145 GRPC_GRPCLB_RECONNECT_JITTER,
1146 GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000,
1147 GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
David Garcia Quintas65318262016-07-29 13:43:38 -07001148}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001149
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001150static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx,
1151 glb_lb_policy *glb_policy) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001152 GPR_ASSERT(glb_policy->lb_call != NULL);
1153 grpc_call_destroy(glb_policy->lb_call);
1154 glb_policy->lb_call = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -07001155
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001156 grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
1157 grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001158
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001159 grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001160 grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
David Garcia Quintas65318262016-07-29 13:43:38 -07001161}
1162
David Garcia Quintas8d489112016-07-29 15:20:42 -07001163/*
1164 * Auxiliary functions and LB client callbacks.
1165 */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001166static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
1167 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001168 GPR_ASSERT(glb_policy->lb_channel != NULL);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001169 if (glb_policy->shutting_down) return;
1170
Craig Tillerc5866662016-11-16 15:25:00 -08001171 lb_call_init_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001172
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001173 if (grpc_lb_glb_trace) {
1174 gpr_log(GPR_INFO, "Query for backends (grpclb: %p, lb_call: %p)",
1175 (void *)glb_policy, (void *)glb_policy->lb_call);
1176 }
1177 GPR_ASSERT(glb_policy->lb_call != NULL);
1178
David Garcia Quintas65318262016-07-29 13:43:38 -07001179 grpc_call_error call_error;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001180 grpc_op ops[4];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001181 memset(ops, 0, sizeof(ops));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001182
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001183 grpc_op *op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -07001184 op->op = GRPC_OP_SEND_INITIAL_METADATA;
1185 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001186 op->flags = 0;
1187 op->reserved = NULL;
1188 op++;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001189
1190 op->op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001191 op->data.recv_initial_metadata.recv_initial_metadata =
1192 &glb_policy->lb_initial_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001193 op->flags = 0;
1194 op->reserved = NULL;
1195 op++;
1196
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001197 GPR_ASSERT(glb_policy->lb_request_payload != NULL);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001198 op->op = GRPC_OP_SEND_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001199 op->data.send_message.send_message = glb_policy->lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001200 op->flags = 0;
1201 op->reserved = NULL;
1202 op++;
1203
1204 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1205 op->data.recv_status_on_client.trailing_metadata =
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001206 &glb_policy->lb_trailing_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001207 op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
1208 op->data.recv_status_on_client.status_details =
1209 &glb_policy->lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001210 op->flags = 0;
1211 op->reserved = NULL;
1212 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001213 /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
1214 * count goes to zero) to be unref'd in lb_on_server_status_received */
1215 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received");
David Garcia Quintas65318262016-07-29 13:43:38 -07001216 call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001217 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1218 &glb_policy->lb_on_server_status_received);
David Garcia Quintas65318262016-07-29 13:43:38 -07001219 GPR_ASSERT(GRPC_CALL_OK == call_error);
1220
1221 op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001222 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001223 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001224 op->flags = 0;
1225 op->reserved = NULL;
1226 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001227 /* take another weak ref to be unref'd in lb_on_response_received */
1228 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received");
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001229 call_error = grpc_call_start_batch_and_execute(
1230 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1231 &glb_policy->lb_on_response_received);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001232 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001233}
1234
Craig Tiller2400bf52017-02-09 16:25:19 -08001235static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg,
1236 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001237 glb_lb_policy *glb_policy = arg;
1238
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001239 grpc_op ops[2];
1240 memset(ops, 0, sizeof(ops));
1241 grpc_op *op = ops;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001242 if (glb_policy->lb_response_payload != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001243 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001244 /* Received data from the LB server. Look inside
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001245 * glb_policy->lb_response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001246 grpc_byte_buffer_reader bbr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001247 grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001248 grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001249 grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001250 grpc_grpclb_serverlist *serverlist =
1251 grpc_grpclb_response_parse_serverlist(response_slice);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001252 if (serverlist != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001253 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001254 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001255 if (grpc_lb_glb_trace) {
Jan Tattermusch2b398082016-10-07 14:40:30 +02001256 gpr_log(GPR_INFO, "Serverlist with %lu servers received",
1257 (unsigned long)serverlist->num_servers);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001258 for (size_t i = 0; i < serverlist->num_servers; ++i) {
1259 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001260 parse_server(serverlist->servers[i], &addr);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001261 char *ipport;
1262 grpc_sockaddr_to_string(&ipport, &addr, false);
1263 gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport);
1264 gpr_free(ipport);
1265 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001266 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001267
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001268 /* update serverlist */
1269 if (serverlist->num_servers > 0) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001270 if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001271 if (grpc_lb_glb_trace) {
1272 gpr_log(GPR_INFO,
1273 "Incoming server list identical to current, ignoring.");
1274 }
David Garcia Quintas1ebcaa22016-11-21 21:52:47 -08001275 grpc_grpclb_destroy_serverlist(serverlist);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001276 } else { /* new serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001277 if (glb_policy->serverlist != NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001278 /* dispose of the old serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001279 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001280 }
David Garcia Quintas1ebcaa22016-11-21 21:52:47 -08001281 /* and update the copy in the glb_lb_policy instance. This serverlist
1282 * instance will be destroyed either upon the next update or in
1283 * glb_destroy() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001284 glb_policy->serverlist = serverlist;
1285
David Garcia Quintas149f09d2016-11-17 20:43:10 -08001286 rr_handover_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001287 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001288 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001289 if (grpc_lb_glb_trace) {
1290 gpr_log(GPR_INFO,
1291 "Received empty server list. Picks will stay pending until a "
1292 "response with > 0 servers is received");
1293 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001294 }
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001295 } else { /* serverlist == NULL */
1296 gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.",
Craig Tiller32df4672016-11-04 08:21:56 -07001297 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
Craig Tiller18b4ba32016-11-09 15:23:42 -08001298 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001299 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001300
David Garcia Quintas246c5642016-11-01 11:16:52 -07001301 if (!glb_policy->shutting_down) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001302 /* keep listening for serverlist updates */
1303 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001304 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001305 op->flags = 0;
1306 op->reserved = NULL;
1307 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001308 /* reuse the "lb_on_response_received" weak ref taken in
1309 * query_for_backends_locked() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001310 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas246c5642016-11-01 11:16:52 -07001311 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1312 &glb_policy->lb_on_response_received); /* loop */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001313 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001314 }
David Garcia Quintase224a762016-11-01 13:00:58 -07001315 } else { /* empty payload: call cancelled. */
1316 /* dispose of the "lb_on_response_received" weak ref taken in
1317 * query_for_backends_locked() and reused in every reception loop */
1318 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1319 "lb_on_response_received_empty_payload");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001320 }
1321}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001322
Craig Tiller2400bf52017-02-09 16:25:19 -08001323static void lb_call_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
1324 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001325 glb_lb_policy *glb_policy = arg;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001326
1327 if (!glb_policy->shutting_down) {
1328 if (grpc_lb_glb_trace) {
1329 gpr_log(GPR_INFO, "Restaring call to LB server (grpclb %p)",
1330 (void *)glb_policy);
1331 }
1332 GPR_ASSERT(glb_policy->lb_call == NULL);
1333 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001334 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001335 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1336 "grpclb_on_retry_timer");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001337}
1338
Craig Tiller2400bf52017-02-09 16:25:19 -08001339static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx,
1340 void *arg, grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001341 glb_lb_policy *glb_policy = arg;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001342
1343 GPR_ASSERT(glb_policy->lb_call != NULL);
1344
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001345 if (grpc_lb_glb_trace) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001346 char *status_details =
1347 grpc_slice_to_c_string(glb_policy->lb_call_status_details);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001348 gpr_log(GPR_DEBUG,
1349 "Status from LB server received. Status = %d, Details = '%s', "
1350 "(call: %p)",
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001351 glb_policy->lb_call_status, status_details,
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001352 (void *)glb_policy->lb_call);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001353 gpr_free(status_details);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001354 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001355
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001356 /* We need to perform cleanups no matter what. */
1357 lb_call_destroy_locked(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001358
1359 if (!glb_policy->shutting_down) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001360 /* if we aren't shutting down, restart the LB client call after some time */
1361 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
1362 gpr_timespec next_try =
1363 gpr_backoff_step(&glb_policy->lb_call_backoff_state, now);
1364 if (grpc_lb_glb_trace) {
1365 gpr_log(GPR_DEBUG, "Connection to LB server lost (grpclb: %p)...",
1366 (void *)glb_policy);
1367 gpr_timespec timeout = gpr_time_sub(next_try, now);
1368 if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) {
1369 gpr_log(GPR_DEBUG, "... retrying in %" PRId64 ".%09d seconds.",
1370 timeout.tv_sec, timeout.tv_nsec);
1371 } else {
1372 gpr_log(GPR_DEBUG, "... retrying immediately.");
1373 }
1374 }
1375 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
Craig Tiller2400bf52017-02-09 16:25:19 -08001376 grpc_closure_init(
1377 &glb_policy->lb_on_call_retry, lb_call_on_retry_timer_locked,
1378 glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001379 grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
Masood Malekghassemib5b43722017-01-05 15:07:26 -08001380 &glb_policy->lb_on_call_retry, now);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001381 }
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001382 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1383 "lb_on_server_status_received");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001384}
1385
David Garcia Quintas8d489112016-07-29 15:20:42 -07001386/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001387static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
Craig Tiller2400bf52017-02-09 16:25:19 -08001388 glb_destroy,
1389 glb_shutdown_locked,
1390 glb_pick_locked,
1391 glb_cancel_pick_locked,
1392 glb_cancel_picks_locked,
1393 glb_ping_one_locked,
1394 glb_exit_idle_locked,
1395 glb_check_connectivity_locked,
1396 glb_notify_on_state_change_locked};
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001397
1398static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
1399
1400static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
1401
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001402static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1403 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1404
1405static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1406
1407grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
1408 return &glb_lb_policy_factory;
1409}
1410
1411/* Plugin registration */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001412void grpc_lb_policy_grpclb_init() {
1413 grpc_register_lb_policy(grpc_glb_lb_factory_create());
1414 grpc_register_tracer("glb", &grpc_lb_glb_trace);
1415}
1416
1417void grpc_lb_policy_grpclb_shutdown() {}