blob: 8a2af4832839129cbdcf91a4afcc684bed36bace [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 Quintas01291502017-02-07 13:26:41 -0800115#include "src/core/ext/lb_policy/grpclb/grpclb_channel.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700116#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
Mark D. Roth046cf762016-09-26 11:13:51 -0700117#include "src/core/lib/channel/channel_args.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200118#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700119#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200120#include "src/core/lib/iomgr/timer.h"
David Garcia Quintas01291502017-02-07 13:26:41 -0800121#include "src/core/lib/slice/slice_hash_table.h"
Craig Tiller18b4ba32016-11-09 15:23:42 -0800122#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -0700123#include "src/core/lib/slice/slice_string_helpers.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200124#include "src/core/lib/support/backoff.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700125#include "src/core/lib/support/string.h"
126#include "src/core/lib/surface/call.h"
127#include "src/core/lib/surface/channel.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700128#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700129
David Garcia Quintas1edfb952016-11-22 17:15:34 -0800130#define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20
131#define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1
132#define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6
133#define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
134#define GRPC_GRPCLB_RECONNECT_JITTER 0.2
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200135
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700136int grpc_lb_glb_trace = 0;
137
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700138/* add lb_token of selected subchannel (address) to the call's initial
139 * metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800140static grpc_error *initial_metadata_add_lb_token(
141 grpc_exec_ctx *exec_ctx, grpc_metadata_batch *initial_metadata,
142 grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem lb_token) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700143 GPR_ASSERT(lb_token_mdelem_storage != NULL);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800144 GPR_ASSERT(!GRPC_MDISNULL(lb_token));
145 return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
146 lb_token_mdelem_storage, lb_token);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700147}
148
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700149typedef struct wrapped_rr_closure_arg {
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700150 /* the closure instance using this struct as argument */
151 grpc_closure wrapper_closure;
152
David Garcia Quintas43339842016-07-18 12:56:09 -0700153 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
154 * calls against the internal RR instance, respectively. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700155 grpc_closure *wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700156
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700157 /* the pick's initial metadata, kept in order to append the LB token for the
158 * pick */
159 grpc_metadata_batch *initial_metadata;
160
161 /* the picked target, used to determine which LB token to add to the pick's
162 * initial metadata */
163 grpc_connected_subchannel **target;
164
165 /* the LB token associated with the pick */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800166 grpc_mdelem lb_token;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700167
168 /* storage for the lb token initial metadata mdelem */
169 grpc_linked_mdelem *lb_token_mdelem_storage;
170
David Garcia Quintas43339842016-07-18 12:56:09 -0700171 /* The RR instance related to the closure */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700172 grpc_lb_policy *rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700173
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700174 /* heap memory to be freed upon closure execution. */
175 void *free_when_done;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700176} wrapped_rr_closure_arg;
177
178/* The \a on_complete closure passed as part of the pick requires keeping a
179 * reference to its associated round robin instance. We wrap this closure in
180 * order to unref the round robin instance upon its invocation */
181static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700182 grpc_error *error) {
David Garcia Quintas43339842016-07-18 12:56:09 -0700183 wrapped_rr_closure_arg *wc_arg = arg;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700184
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200185 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
Craig Tiller91031da2016-12-28 15:44:25 -0800186 grpc_closure_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200187
188 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas6493a732016-11-22 10:25:52 -0800189 /* if *target is NULL, no pick has been made by the RR policy (eg, all
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700190 * addresses failed to connect). There won't be any user_data/token
191 * available */
David Garcia Quintas6493a732016-11-22 10:25:52 -0800192 if (*wc_arg->target != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800193 if (!GRPC_MDISNULL(wc_arg->lb_token)) {
194 initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800195 wc_arg->lb_token_mdelem_storage,
196 GRPC_MDELEM_REF(wc_arg->lb_token));
197 } else {
198 gpr_log(GPR_ERROR,
199 "No LB token for connected subchannel pick %p (from RR "
200 "instance %p).",
201 (void *)*wc_arg->target, (void *)wc_arg->rr_policy);
202 abort();
203 }
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700204 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200205 if (grpc_lb_glb_trace) {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800206 gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200207 }
208 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700209 }
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700210 GPR_ASSERT(wc_arg->free_when_done != NULL);
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700211 gpr_free(wc_arg->free_when_done);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700212}
213
David Garcia Quintasea11d162016-07-14 17:27:28 -0700214/* Linked list of pending pick requests. It stores all information needed to
215 * eventually call (Round Robin's) pick() on them. They mainly stay pending
216 * waiting for the RR policy to be created/updated.
217 *
218 * One particularity is the wrapping of the user-provided \a on_complete closure
219 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
220 * order to correctly unref the RR policy instance upon completion of the pick.
221 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700222typedef struct pending_pick {
223 struct pending_pick *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700224
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700225 /* original pick()'s arguments */
226 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700227
228 /* output argument where to store the pick()ed connected subchannel, or NULL
229 * upon error. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700230 grpc_connected_subchannel **target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700231
David Garcia Quintas43339842016-07-18 12:56:09 -0700232 /* args for wrapped_on_complete */
233 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700234} pending_pick;
235
David Garcia Quintas8aace512016-08-15 14:55:12 -0700236static void add_pending_pick(pending_pick **root,
237 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas65318262016-07-29 13:43:38 -0700238 grpc_connected_subchannel **target,
239 grpc_closure *on_complete) {
240 pending_pick *pp = gpr_malloc(sizeof(*pp));
241 memset(pp, 0, sizeof(pending_pick));
242 memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
243 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700244 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700245 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700246 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700247 pp->wrapped_on_complete_arg.target = target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700248 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
249 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
250 pick_args->lb_token_mdelem_storage;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700251 pp->wrapped_on_complete_arg.free_when_done = pp;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700252 grpc_closure_init(&pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800253 wrapped_rr_closure, &pp->wrapped_on_complete_arg,
254 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700255 *root = pp;
256}
257
David Garcia Quintasea11d162016-07-14 17:27:28 -0700258/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700259typedef struct pending_ping {
260 struct pending_ping *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700261
David Garcia Quintas43339842016-07-18 12:56:09 -0700262 /* args for wrapped_notify */
263 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700264} pending_ping;
265
David Garcia Quintas65318262016-07-29 13:43:38 -0700266static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
267 pending_ping *pping = gpr_malloc(sizeof(*pping));
268 memset(pping, 0, sizeof(pending_ping));
269 memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
David Garcia Quintas65318262016-07-29 13:43:38 -0700270 pping->wrapped_notify_arg.wrapped_closure = notify;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700271 pping->wrapped_notify_arg.free_when_done = pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700272 pping->next = *root;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700273 grpc_closure_init(&pping->wrapped_notify_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800274 wrapped_rr_closure, &pping->wrapped_notify_arg,
275 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700276 *root = pping;
277}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700278
David Garcia Quintas8d489112016-07-29 15:20:42 -0700279/*
280 * glb_lb_policy
281 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700282typedef struct rr_connectivity_data rr_connectivity_data;
David Garcia Quintas65318262016-07-29 13:43:38 -0700283static const grpc_lb_policy_vtable glb_lb_policy_vtable;
284typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700285 /** base policy: must be first */
286 grpc_lb_policy base;
287
288 /** mutex protecting remaining members */
289 gpr_mu mu;
290
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700291 /** who the client is trying to communicate with */
Mark D. Rothd1604af2016-09-22 11:20:27 -0700292 const char *server_name;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700293 grpc_client_channel_factory *cc_factory;
Mark D. Roth046cf762016-09-26 11:13:51 -0700294 grpc_channel_args *args;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700295
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700296 /** deadline for the LB's call */
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700297 gpr_timespec deadline;
298
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700299 /** for communicating with the LB server */
David Garcia Quintasea11d162016-07-14 17:27:28 -0700300 grpc_channel *lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700301
302 /** the RR policy to use of the backend servers returned by the LB server */
303 grpc_lb_policy *rr_policy;
304
305 bool started_picking;
306
307 /** our connectivity state tracker */
308 grpc_connectivity_state_tracker state_tracker;
309
David Garcia Quintasea11d162016-07-14 17:27:28 -0700310 /** stores the deserialized response from the LB. May be NULL until one such
311 * response has arrived. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700312 grpc_grpclb_serverlist *serverlist;
313
David Garcia Quintasea11d162016-07-14 17:27:28 -0700314 /** list of picks that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700315 pending_pick *pending_picks;
316
David Garcia Quintasea11d162016-07-14 17:27:28 -0700317 /** list of pings that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700318 pending_ping *pending_pings;
319
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200320 bool shutting_down;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700321
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200322 /************************************************************/
323 /* client data associated with the LB server communication */
324 /************************************************************/
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100325 /* Status from the LB server has been received. This signals the end of the LB
326 * call. */
327 grpc_closure lb_on_server_status_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200328
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100329 /* A response from the LB server has been received. Process it */
330 grpc_closure lb_on_response_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200331
Masood Malekghassemib5b43722017-01-05 15:07:26 -0800332 /* LB call retry timer callback. */
333 grpc_closure lb_on_call_retry;
334
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200335 grpc_call *lb_call; /* streaming call to the LB server, */
336
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100337 grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */
338 grpc_metadata_array
339 lb_trailing_metadata_recv; /* trailing MD from LB server */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200340
341 /* what's being sent to the LB server. Note that its value may vary if the LB
342 * server indicates a redirect. */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100343 grpc_byte_buffer *lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200344
David Garcia Quintas246c5642016-11-01 11:16:52 -0700345 /* response the LB server, if any. Processed in lb_on_response_received() */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100346 grpc_byte_buffer *lb_response_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200347
David Garcia Quintas246c5642016-11-01 11:16:52 -0700348 /* call status code and details, set in lb_on_server_status_received() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200349 grpc_status_code lb_call_status;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800350 grpc_slice lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200351
352 /** LB call retry backoff state */
353 gpr_backoff lb_call_backoff_state;
354
355 /** LB call retry timer */
356 grpc_timer lb_call_retry_timer;
David Garcia Quintas65318262016-07-29 13:43:38 -0700357} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700358
David Garcia Quintas65318262016-07-29 13:43:38 -0700359/* Keeps track and reacts to changes in connectivity of the RR instance */
360struct rr_connectivity_data {
361 grpc_closure on_change;
362 grpc_connectivity_state state;
363 glb_lb_policy *glb_policy;
364};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700365
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700366static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
367 bool log) {
368 const grpc_grpclb_ip_address *ip = &server->ip_address;
369 if (server->port >> 16 != 0) {
370 if (log) {
371 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200372 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
373 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700374 }
375 return false;
376 }
377
378 if (ip->size != 4 && ip->size != 16) {
379 if (log) {
380 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200381 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700382 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200383 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700384 }
385 return false;
386 }
387 return true;
388}
389
Mark D. Roth16883a32016-10-21 10:30:58 -0700390/* vtable for LB tokens in grpc_lb_addresses. */
Mark D. Roth557c9902016-10-24 11:12:05 -0700391static void *lb_token_copy(void *token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800392 return token == NULL
393 ? NULL
394 : (void *)GRPC_MDELEM_REF((grpc_mdelem){(uintptr_t)token}).payload;
Mark D. Roth16883a32016-10-21 10:30:58 -0700395}
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800396static void lb_token_destroy(grpc_exec_ctx *exec_ctx, void *token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800397 if (token != NULL) {
398 GRPC_MDELEM_UNREF(exec_ctx, (grpc_mdelem){(uintptr_t)token});
399 }
Mark D. Roth16883a32016-10-21 10:30:58 -0700400}
Mark D. Roth557c9902016-10-24 11:12:05 -0700401static int lb_token_cmp(void *token1, void *token2) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700402 if (token1 > token2) return 1;
403 if (token1 < token2) return -1;
404 return 0;
405}
406static const grpc_lb_user_data_vtable lb_token_vtable = {
407 lb_token_copy, lb_token_destroy, lb_token_cmp};
408
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100409static void parse_server(const grpc_grpclb_server *server,
410 grpc_resolved_address *addr) {
411 const uint16_t netorder_port = htons((uint16_t)server->port);
412 /* the addresses are given in binary format (a in(6)_addr struct) in
413 * server->ip_address.bytes. */
414 const grpc_grpclb_ip_address *ip = &server->ip_address;
415 memset(addr, 0, sizeof(*addr));
416 if (ip->size == 4) {
417 addr->len = sizeof(struct sockaddr_in);
418 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
419 addr4->sin_family = AF_INET;
420 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
421 addr4->sin_port = netorder_port;
422 } else if (ip->size == 16) {
423 addr->len = sizeof(struct sockaddr_in6);
424 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr->addr;
David Garcia Quintas107ca162016-11-02 18:17:03 -0700425 addr6->sin6_family = AF_INET6;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100426 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
427 addr6->sin6_port = netorder_port;
428 }
429}
430
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700431/* Returns addresses extracted from \a serverlist. */
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800432static grpc_lb_addresses *process_serverlist_locked(
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800433 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700434 size_t num_valid = 0;
435 /* first pass: count how many are valid in order to allocate the necessary
436 * memory in a single block */
437 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700438 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700439 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700440 if (num_valid == 0) return NULL;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700441
Mark D. Roth16883a32016-10-21 10:30:58 -0700442 grpc_lb_addresses *lb_addresses =
443 grpc_lb_addresses_create(num_valid, &lb_token_vtable);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700444
445 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700446 * to the outside world) to be read by the RR policy during its creation.
447 * Given that the validity tests are very cheap, they are performed again
448 * instead of marking the valid ones during the first pass, as this would
449 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700450 size_t addr_idx = 0;
451 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
452 GPR_ASSERT(addr_idx < num_valid);
453 const grpc_grpclb_server *server = serverlist->servers[sl_idx];
454 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700455
456 /* address processing */
Mark D. Rothc5c38782016-09-16 08:51:01 -0700457 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100458 parse_server(server, &addr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700459
460 /* lb token processing */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700461 void *user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700462 if (server->has_load_balance_token) {
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200463 const size_t lb_token_max_length =
464 GPR_ARRAY_SIZE(server->load_balance_token);
465 const size_t lb_token_length =
466 strnlen(server->load_balance_token, lb_token_max_length);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800467 grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
468 server->load_balance_token, lb_token_length);
469 user_data = (void *)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
470 lb_token_mdstr)
471 .payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700472 } else {
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800473 char *uri = grpc_sockaddr_to_uri(&addr);
474 gpr_log(GPR_INFO,
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700475 "Missing LB token for backend address '%s'. The empty token will "
476 "be used instead",
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800477 uri);
478 gpr_free(uri);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800479 user_data = (void *)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700480 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700481
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700482 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
483 false /* is_balancer */,
Mark D. Rothc5c38782016-09-16 08:51:01 -0700484 NULL /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700485 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700486 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700487 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700488 return lb_addresses;
489}
490
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800491/* returns true if the new RR policy should replace the current one, if any */
492static bool update_lb_connectivity_status_locked(
493 grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
494 grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800495 const grpc_connectivity_state curr_glb_state =
496 grpc_connectivity_state_check(&glb_policy->state_tracker);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800497
498 /* The new connectivity status is a function of the previous one and the new
499 * input coming from the status of the RR policy.
500 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800501 * current state (grpclb's)
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800502 * |
503 * v || I | C | R | TF | SD | <- new state (RR's)
504 * ===++====+=====+=====+======+======+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800505 * I || I | C | R | [I] | [I] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800506 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800507 * C || I | C | R | [C] | [C] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800508 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800509 * R || I | C | R | [R] | [R] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800510 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800511 * TF || I | C | R | [TF] | [TF] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800512 * ---++----+-----+-----+------+------+
513 * SD || NA | NA | NA | NA | NA | (*)
514 * ---++----+-----+-----+------+------+
515 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800516 * A [STATE] indicates that the old RR policy is kept. In those cases, STATE
517 * is the current state of grpclb, which is left untouched.
518 *
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800519 * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
520 * the previous RR instance.
521 *
522 * Note that the status is never updated to SHUTDOWN as a result of calling
523 * this function. Only glb_shutdown() has the power to set that state.
524 *
525 * (*) This function mustn't be called during shutting down. */
526 GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
527
528 switch (new_rr_state) {
529 case GRPC_CHANNEL_TRANSIENT_FAILURE:
530 case GRPC_CHANNEL_SHUTDOWN:
531 GPR_ASSERT(new_rr_state_error != GRPC_ERROR_NONE);
532 return false; /* don't replace the RR policy */
533 case GRPC_CHANNEL_INIT:
534 case GRPC_CHANNEL_IDLE:
535 case GRPC_CHANNEL_CONNECTING:
536 case GRPC_CHANNEL_READY:
537 GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE);
538 }
539
540 if (grpc_lb_glb_trace) {
541 gpr_log(GPR_INFO,
542 "Setting grpclb's state to %s from new RR policy %p state.",
543 grpc_connectivity_state_name(new_rr_state),
544 (void *)glb_policy->rr_policy);
545 }
546 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
547 new_rr_state, GRPC_ERROR_REF(new_rr_state_error),
548 "update_lb_connectivity_status_locked");
549 return true;
550}
551
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700552/* perform a pick over \a rr_policy. Given that a pick can return immediately
553 * (ignoring its completion callback) we need to perform the cleanups this
554 * callback would be otherwise resposible for */
David Garcia Quintas20359062016-10-15 15:22:51 -0700555static bool pick_from_internal_rr_locked(
556 grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy,
557 const grpc_lb_policy_pick_args *pick_args,
558 grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
559 GPR_ASSERT(rr_policy != NULL);
560 const bool pick_done =
561 grpc_lb_policy_pick(exec_ctx, rr_policy, pick_args, target,
562 (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
563 if (pick_done) {
564 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
565 if (grpc_lb_glb_trace) {
566 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
567 (intptr_t)wc_arg->rr_policy);
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700568 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200569 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700570
David Garcia Quintas20359062016-10-15 15:22:51 -0700571 /* add the load reporting initial metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800572 initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
David Garcia Quintas20359062016-10-15 15:22:51 -0700573 pick_args->lb_token_mdelem_storage,
574 GRPC_MDELEM_REF(wc_arg->lb_token));
575
576 gpr_free(wc_arg);
577 }
578 /* else, the pending pick will be registered and taken care of by the
579 * pending pick list inside the RR policy (glb_policy->rr_policy).
580 * Eventually, wrapped_on_complete will be called, which will -among other
581 * things- add the LB token to the call's initial metadata */
David Garcia Quintas20359062016-10-15 15:22:51 -0700582 return pick_done;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700583}
584
David Garcia Quintas90712d52016-10-13 19:33:04 -0700585static grpc_lb_policy *create_rr_locked(
586 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist,
587 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700588 GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700589
590 grpc_lb_policy_args args;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700591 memset(&args, 0, sizeof(args));
David Garcia Quintas65318262016-07-29 13:43:38 -0700592 args.client_channel_factory = glb_policy->cc_factory;
Craig Tillerb28c7e82016-11-18 10:29:04 -0800593 grpc_lb_addresses *addresses =
594 process_serverlist_locked(exec_ctx, serverlist);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700595
596 // Replace the LB addresses in the channel args that we pass down to
597 // the subchannel.
Mark D. Roth557c9902016-10-24 11:12:05 -0700598 static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200599 const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700600 args.args = grpc_channel_args_copy_and_add_and_remove(
601 glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
602 1);
David Garcia Quintas65318262016-07-29 13:43:38 -0700603
604 grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200605 GPR_ASSERT(rr != NULL);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800606 grpc_lb_addresses_destroy(exec_ctx, addresses);
607 grpc_channel_args_destroy(exec_ctx, args.args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700608 return rr;
609}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700610
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200611static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
612 grpc_error *error);
613/* glb_policy->rr_policy may be NULL (initial handover) */
David Garcia Quintas90712d52016-10-13 19:33:04 -0700614static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800615 glb_lb_policy *glb_policy) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700616 GPR_ASSERT(glb_policy->serverlist != NULL &&
617 glb_policy->serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700618
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800619 if (glb_policy->shutting_down) return;
620
David Garcia Quintas4283a262016-11-18 10:43:56 -0800621 grpc_lb_policy *new_rr_policy =
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200622 create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy);
David Garcia Quintas4283a262016-11-18 10:43:56 -0800623 if (new_rr_policy == NULL) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800624 gpr_log(GPR_ERROR,
625 "Failure creating a RoundRobin policy for serverlist update with "
626 "%lu entries. The previous RR instance (%p), if any, will continue "
627 "to be used. Future updates from the LB will attempt to create new "
628 "instances.",
629 (unsigned long)glb_policy->serverlist->num_servers,
David Garcia Quintas4283a262016-11-18 10:43:56 -0800630 (void *)glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800631 return;
David Garcia Quintas65318262016-07-29 13:43:38 -0700632 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200633
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800634 grpc_error *new_rr_state_error = NULL;
635 const grpc_connectivity_state new_rr_state =
David Garcia Quintas4283a262016-11-18 10:43:56 -0800636 grpc_lb_policy_check_connectivity(exec_ctx, new_rr_policy,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800637 &new_rr_state_error);
638 /* Connectivity state is a function of the new RR policy just created */
639 const bool replace_old_rr = update_lb_connectivity_status_locked(
640 exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
641
642 if (!replace_old_rr) {
643 /* dispose of the new RR policy that won't be used after all */
David Garcia Quintas4283a262016-11-18 10:43:56 -0800644 GRPC_LB_POLICY_UNREF(exec_ctx, new_rr_policy, "rr_handover_no_replace");
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800645 if (grpc_lb_glb_trace) {
646 gpr_log(GPR_INFO,
647 "Keeping old RR policy (%p) despite new serverlist: new RR "
648 "policy was in %s connectivity state.",
David Garcia Quintas4283a262016-11-18 10:43:56 -0800649 (void *)glb_policy->rr_policy,
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800650 grpc_connectivity_state_name(new_rr_state));
651 }
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800652 return;
653 }
654
655 if (grpc_lb_glb_trace) {
David Garcia Quintase7d2f212016-11-17 22:04:22 -0800656 gpr_log(GPR_INFO, "Created RR policy (%p) to replace old RR (%p)",
David Garcia Quintas4283a262016-11-18 10:43:56 -0800657 (void *)new_rr_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800658 }
659
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700660 if (glb_policy->rr_policy != NULL) {
David Garcia Quintas41bef452016-07-28 19:19:58 -0700661 /* if we are phasing out an existing RR instance, unref it. */
David Garcia Quintas65318262016-07-29 13:43:38 -0700662 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "rr_handover");
663 }
664
David Garcia Quintas4283a262016-11-18 10:43:56 -0800665 /* Finally update the RR policy to the newly created one */
666 glb_policy->rr_policy = new_rr_policy;
David Garcia Quintas65318262016-07-29 13:43:38 -0700667
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800668 /* Add the gRPC LB's interested_parties pollset_set to that of the newly
669 * created RR policy. This will make the RR policy progress upon activity on
670 * gRPC LB, which in turn is tied to the application's call */
Yuchen Zengb4291642016-09-01 19:17:14 -0700671 grpc_pollset_set_add_pollset_set(exec_ctx,
672 glb_policy->rr_policy->interested_parties,
673 glb_policy->base.interested_parties);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200674
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800675 /* Allocate the data for the tracking of the new RR policy's connectivity.
676 * It'll be deallocated in glb_rr_connectivity_changed() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200677 rr_connectivity_data *rr_connectivity =
678 gpr_malloc(sizeof(rr_connectivity_data));
679 memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
680 grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
Craig Tiller91031da2016-12-28 15:44:25 -0800681 rr_connectivity, grpc_schedule_on_exec_ctx);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200682 rr_connectivity->glb_policy = glb_policy;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800683 rr_connectivity->state = new_rr_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200684
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800685 /* Subscribe to changes to the connectivity of the new RR */
David Garcia Quintase224a762016-11-01 13:00:58 -0700686 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200687 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
688 &rr_connectivity->state,
689 &rr_connectivity->on_change);
David Garcia Quintas65318262016-07-29 13:43:38 -0700690 grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
691
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800692 /* Update picks and pings in wait */
David Garcia Quintas65318262016-07-29 13:43:38 -0700693 pending_pick *pp;
694 while ((pp = glb_policy->pending_picks)) {
695 glb_policy->pending_picks = pp->next;
696 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
697 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
698 if (grpc_lb_glb_trace) {
699 gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
700 (intptr_t)glb_policy->rr_policy);
701 }
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700702 pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
703 &pp->pick_args, pp->target,
704 &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700705 }
706
707 pending_ping *pping;
708 while ((pping = glb_policy->pending_pings)) {
709 glb_policy->pending_pings = pping->next;
710 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
711 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
712 if (grpc_lb_glb_trace) {
713 gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
714 (intptr_t)glb_policy->rr_policy);
715 }
716 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700717 &pping->wrapped_notify_arg.wrapper_closure);
David Garcia Quintas65318262016-07-29 13:43:38 -0700718 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700719}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700720
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700721static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
722 grpc_error *error) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800723 rr_connectivity_data *rr_connectivity = arg;
724 glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700725
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800726 gpr_mu_lock(&glb_policy->mu);
727 const bool shutting_down = glb_policy->shutting_down;
David Garcia Quintas4283a262016-11-18 10:43:56 -0800728 bool unref_needed = false;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800729 GRPC_ERROR_REF(error);
730
731 if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) {
732 /* RR policy shutting down. Don't renew subscription and free the arg of
733 * this callback. In addition we need to stash away the current policy to
734 * be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last
735 * one, the policy would be destroyed, alongside the lock, which would
736 * result in a use-after-free */
David Garcia Quintas4283a262016-11-18 10:43:56 -0800737 unref_needed = true;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800738 gpr_free(rr_connectivity);
739 } else { /* rr state != SHUTDOWN && !shutting down: biz as usual */
740 update_lb_connectivity_status_locked(exec_ctx, glb_policy,
741 rr_connectivity->state, error);
742 /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200743 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800744 &rr_connectivity->state,
745 &rr_connectivity->on_change);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700746 }
David Garcia Quintasf9532952016-11-08 14:14:25 -0800747 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas4283a262016-11-18 10:43:56 -0800748 if (unref_needed) {
749 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
750 "rr_connectivity_cb");
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800751 }
752 GRPC_ERROR_UNREF(error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700753}
754
David Garcia Quintas01291502017-02-07 13:26:41 -0800755static void destroy_balancer_name(grpc_exec_ctx *exec_ctx,
756 void *balancer_name) {
757 gpr_free(balancer_name);
758}
759
760static void *copy_balancer_name(void *balancer_name) {
761 return gpr_strdup(balancer_name);
762}
763
764static grpc_slice_hash_table_entry targets_info_entry_create(
765 const char *address, const char *balancer_name) {
766 static const grpc_slice_hash_table_vtable vtable = {destroy_balancer_name,
767 copy_balancer_name};
768 grpc_slice_hash_table_entry entry;
769 entry.key = grpc_slice_from_copied_string(address);
770 entry.value = (void *)balancer_name;
771 entry.vtable = &vtable;
772 return entry;
773}
774
775/* Returns the target URI for the LB service whose addresses are in \a
776 * addresses. Using this URI, a bidirectional streaming channel will be created
777 * for the reception of load balancing updates.
778 *
779 * The output argument \a targets_info will be updated to contain a mapping of
780 * "LB server address" to "balancer name", as reported by the naming system.
781 * This mapping will be propagated via the channel arguments of the
782 * aforementioned LB streaming channel, to be used by the security connector for
783 * secure naming checks. The user is responsible for freeing \a targets_info. */
784static char *get_lb_uri_target_addresses(grpc_exec_ctx *exec_ctx,
785 const grpc_lb_addresses *addresses,
786 grpc_slice_hash_table **targets_info) {
787 size_t num_grpclb_addrs = 0;
788 for (size_t i = 0; i < addresses->num_addresses; ++i) {
789 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
790 }
791 /* All input addresses come from a resolver that claims they are LB services.
792 * It's the resolver's responsibility to make sure this policy is only
793 * instantiated and used in that case. Otherwise, something has gone wrong. */
794 GPR_ASSERT(num_grpclb_addrs > 0);
795
796 grpc_slice_hash_table_entry *targets_info_entries =
797 gpr_malloc(sizeof(*targets_info_entries) * num_grpclb_addrs);
798
799 /* construct a target ipvX://ip1:port1,ip2:port2,... from the addresses in \a
800 * addresses */
801 /* TODO(dgq): support mixed ip version */
802 char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
803 size_t addr_index = 0;
804
805 for (size_t i = 0; i < addresses->num_addresses; i++) {
806 if (addresses->addresses[i].user_data != NULL) {
807 gpr_log(GPR_ERROR,
808 "This LB policy doesn't support user data. It will be ignored");
809 }
810 if (addresses->addresses[i].is_balancer) {
811 char *addr_str;
812 GPR_ASSERT(grpc_sockaddr_to_string(
813 &addr_str, &addresses->addresses[i].address, true) > 0);
814 targets_info_entries[addr_index] = targets_info_entry_create(
815 addr_str, addresses->addresses[i].balancer_name);
816 addr_strs[addr_index++] = addr_str;
817 }
818 }
819 GPR_ASSERT(addr_index == num_grpclb_addrs);
820
821 size_t uri_path_len;
822 char *uri_path = gpr_strjoin_sep((const char **)addr_strs, num_grpclb_addrs,
823 ",", &uri_path_len);
824 for (size_t i = 0; i < num_grpclb_addrs; i++) gpr_free(addr_strs[i]);
825 gpr_free(addr_strs);
826
827 char *target_uri_str = NULL;
828 /* TODO(dgq): Don't assume all addresses will share the scheme of the first
829 * one */
830 gpr_asprintf(&target_uri_str, "%s:%s",
831 grpc_sockaddr_get_uri_scheme(&addresses->addresses[0].address),
832 uri_path);
833 gpr_free(uri_path);
834
835 *targets_info =
836 grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries);
837 for (size_t i = 0; i < num_grpclb_addrs; i++) {
838 grpc_slice_unref_internal(exec_ctx, targets_info_entries[i].key);
839 }
840 gpr_free(targets_info_entries);
841
842 return target_uri_str;
843}
844
David Garcia Quintas65318262016-07-29 13:43:38 -0700845static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
846 grpc_lb_policy_factory *factory,
847 grpc_lb_policy_args *args) {
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700848 /* Count the number of gRPC-LB addresses. There must be at least one.
849 * TODO(roth): For now, we ignore non-balancer addresses, but in the
850 * future, we may change the behavior such that we fall back to using
851 * the non-balancer addresses if we cannot reach any balancers. At that
852 * time, this should be changed to allow a list with no balancer addresses,
853 * since the resolver might fail to return a balancer address even when
854 * this is the right LB policy to use. */
Mark D. Roth201db7d2016-12-12 09:36:02 -0800855 const grpc_arg *arg =
856 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700857 GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700858 grpc_lb_addresses *addresses = arg->value.pointer.p;
Mark D. Rothf655c852016-09-06 10:40:38 -0700859 size_t num_grpclb_addrs = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700860 for (size_t i = 0; i < addresses->num_addresses; ++i) {
861 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
Mark D. Rothf655c852016-09-06 10:40:38 -0700862 }
863 if (num_grpclb_addrs == 0) return NULL;
864
David Garcia Quintas65318262016-07-29 13:43:38 -0700865 glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
866 memset(glb_policy, 0, sizeof(*glb_policy));
867
Mark D. Roth201db7d2016-12-12 09:36:02 -0800868 /* Get server name. */
869 arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
870 GPR_ASSERT(arg != NULL);
871 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
David Garcia Quintas855a1062016-12-16 13:11:49 -0800872 grpc_uri *uri = grpc_uri_parse(arg->value.string, true);
873 GPR_ASSERT(uri->path[0] != '\0');
874 glb_policy->server_name =
875 gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
876 if (grpc_lb_glb_trace) {
877 gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.",
878 glb_policy->server_name);
879 }
Mark D. Roth201db7d2016-12-12 09:36:02 -0800880 grpc_uri_destroy(uri);
881
David Garcia Quintas65318262016-07-29 13:43:38 -0700882 glb_policy->cc_factory = args->client_channel_factory;
Mark D. Roth98abfd32016-10-21 08:10:51 -0700883 glb_policy->args = grpc_channel_args_copy(args->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700884 GPR_ASSERT(glb_policy->cc_factory != NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700885
David Garcia Quintas01291502017-02-07 13:26:41 -0800886 grpc_slice_hash_table *targets_info = NULL;
887 /* Create a client channel over them to communicate with a LB service */
888 char *lb_service_target_addresses =
889 get_lb_uri_target_addresses(exec_ctx, addresses, &targets_info);
890 grpc_channel_args *lb_channel_args =
891 get_lb_channel_args(exec_ctx, targets_info, args->args);
892 glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
893 exec_ctx, lb_service_target_addresses, args->client_channel_factory,
894 lb_channel_args);
895 grpc_slice_hash_table_unref(exec_ctx, targets_info);
896 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
897 gpr_free(lb_service_target_addresses);
David Garcia Quintas65318262016-07-29 13:43:38 -0700898 if (glb_policy->lb_channel == NULL) {
899 gpr_free(glb_policy);
900 return NULL;
901 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700902 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
903 gpr_mu_init(&glb_policy->mu);
904 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
905 "grpclb");
906 return &glb_policy->base;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700907}
908
David Garcia Quintas65318262016-07-29 13:43:38 -0700909static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
910 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
911 GPR_ASSERT(glb_policy->pending_picks == NULL);
912 GPR_ASSERT(glb_policy->pending_pings == NULL);
Mark D. Rothd1604af2016-09-22 11:20:27 -0700913 gpr_free((void *)glb_policy->server_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800914 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700915 grpc_channel_destroy(glb_policy->lb_channel);
916 glb_policy->lb_channel = NULL;
917 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
918 if (glb_policy->serverlist != NULL) {
919 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
920 }
921 gpr_mu_destroy(&glb_policy->mu);
922 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700923}
924
David Garcia Quintas65318262016-07-29 13:43:38 -0700925static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
926 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
927 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200928 glb_policy->shutting_down = true;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700929
David Garcia Quintas65318262016-07-29 13:43:38 -0700930 pending_pick *pp = glb_policy->pending_picks;
931 glb_policy->pending_picks = NULL;
932 pending_ping *pping = glb_policy->pending_pings;
933 glb_policy->pending_pings = NULL;
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800934 if (glb_policy->rr_policy) {
935 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
936 }
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800937 grpc_connectivity_state_set(
938 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
939 GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown");
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800940 /* We need a copy of the lb_call pointer because we can't cancell the call
941 * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
942 * the cancel, needs to acquire that same lock */
943 grpc_call *lb_call = glb_policy->lb_call;
David Garcia Quintas65318262016-07-29 13:43:38 -0700944 gpr_mu_unlock(&glb_policy->mu);
945
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800946 /* glb_policy->lb_call and this local lb_call must be consistent at this point
947 * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
948 * of query_for_backends_locked, which can only be invoked while
949 * glb_policy->shutting_down is false. */
950 if (lb_call != NULL) {
951 grpc_call_cancel(lb_call, NULL);
952 /* lb_on_server_status_received will pick up the cancel and clean up */
953 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700954 while (pp != NULL) {
955 pending_pick *next = pp->next;
956 *pp->target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800957 grpc_closure_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
958 GRPC_ERROR_NONE);
David Garcia Quintas65318262016-07-29 13:43:38 -0700959 pp = next;
960 }
961
962 while (pping != NULL) {
963 pending_ping *next = pping->next;
Craig Tiller91031da2016-12-28 15:44:25 -0800964 grpc_closure_sched(exec_ctx, &pping->wrapped_notify_arg.wrapper_closure,
965 GRPC_ERROR_NONE);
David Garcia Quintas65318262016-07-29 13:43:38 -0700966 pping = next;
967 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700968}
969
970static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
Mark D. Roth5f844002016-09-08 08:20:53 -0700971 grpc_connected_subchannel **target,
972 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700973 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
974 gpr_mu_lock(&glb_policy->mu);
975 pending_pick *pp = glb_policy->pending_picks;
976 glb_policy->pending_picks = NULL;
977 while (pp != NULL) {
978 pending_pick *next = pp->next;
979 if (pp->target == target) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700980 *target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800981 grpc_closure_sched(
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700982 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800983 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -0700984 } else {
985 pp->next = glb_policy->pending_picks;
986 glb_policy->pending_picks = pp;
987 }
988 pp = next;
989 }
990 gpr_mu_unlock(&glb_policy->mu);
Mark D. Roth5f844002016-09-08 08:20:53 -0700991 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700992}
993
David Garcia Quintas65318262016-07-29 13:43:38 -0700994static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
995 uint32_t initial_metadata_flags_mask,
Mark D. Rothe65ff112016-09-09 13:48:38 -0700996 uint32_t initial_metadata_flags_eq,
997 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700998 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
999 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas65318262016-07-29 13:43:38 -07001000 pending_pick *pp = glb_policy->pending_picks;
1001 glb_policy->pending_picks = NULL;
1002 while (pp != NULL) {
1003 pending_pick *next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001004 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -07001005 initial_metadata_flags_eq) {
Craig Tiller91031da2016-12-28 15:44:25 -08001006 grpc_closure_sched(
David Garcia Quintas97ba6422016-10-14 13:06:45 -07001007 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -08001008 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -07001009 } else {
1010 pp->next = glb_policy->pending_picks;
1011 glb_policy->pending_picks = pp;
1012 }
1013 pp = next;
1014 }
1015 gpr_mu_unlock(&glb_policy->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -07001016 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001017}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001018
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001019static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
1020 glb_lb_policy *glb_policy);
1021static void start_picking_locked(grpc_exec_ctx *exec_ctx,
1022 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001023 glb_policy->started_picking = true;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001024 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
1025 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001026}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001027
David Garcia Quintas65318262016-07-29 13:43:38 -07001028static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
1029 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1030 gpr_mu_lock(&glb_policy->mu);
1031 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001032 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001033 }
1034 gpr_mu_unlock(&glb_policy->mu);
1035}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001036
David Garcia Quintas65318262016-07-29 13:43:38 -07001037static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
David Garcia Quintas8aace512016-08-15 14:55:12 -07001038 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas331b9c02016-09-12 18:37:05 -07001039 grpc_connected_subchannel **target, void **user_data,
David Garcia Quintas65318262016-07-29 13:43:38 -07001040 grpc_closure *on_complete) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001041 if (pick_args->lb_token_mdelem_storage == NULL) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001042 *target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -08001043 grpc_closure_sched(
David Garcia Quintas6cc44fc2016-09-12 23:04:35 -07001044 exec_ctx, on_complete,
1045 GRPC_ERROR_CREATE("No mdelem storage for the LB token. Load reporting "
Craig Tiller91031da2016-12-28 15:44:25 -08001046 "won't work without it. Failing"));
Mark D. Roth1e5f6af2016-10-07 08:32:58 -07001047 return 0;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001048 }
1049
David Garcia Quintas65318262016-07-29 13:43:38 -07001050 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1051 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas5cf3c372016-10-03 14:30:03 -07001052 glb_policy->deadline = pick_args->deadline;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001053 bool pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001054
1055 if (glb_policy->rr_policy != NULL) {
1056 if (grpc_lb_glb_trace) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001057 gpr_log(GPR_INFO, "grpclb %p about to PICK from RR %p",
1058 (void *)glb_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001059 }
1060 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
David Garcia Quintas8aace512016-08-15 14:55:12 -07001061
David Garcia Quintas97ba6422016-10-14 13:06:45 -07001062 wrapped_rr_closure_arg *wc_arg = gpr_malloc(sizeof(wrapped_rr_closure_arg));
David Garcia Quintas90712d52016-10-13 19:33:04 -07001063 memset(wc_arg, 0, sizeof(wrapped_rr_closure_arg));
David Garcia Quintas331b9c02016-09-12 18:37:05 -07001064
Craig Tiller91031da2016-12-28 15:44:25 -08001065 grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
1066 grpc_schedule_on_exec_ctx);
David Garcia Quintas90712d52016-10-13 19:33:04 -07001067 wc_arg->rr_policy = glb_policy->rr_policy;
1068 wc_arg->target = target;
1069 wc_arg->wrapped_closure = on_complete;
1070 wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
1071 wc_arg->initial_metadata = pick_args->initial_metadata;
David Garcia Quintas97ba6422016-10-14 13:06:45 -07001072 wc_arg->free_when_done = wc_arg;
David Garcia Quintas58c18e72016-10-14 15:23:45 -07001073 pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas20359062016-10-15 15:22:51 -07001074 pick_args, target, wc_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -07001075 } else {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001076 if (grpc_lb_glb_trace) {
1077 gpr_log(GPR_DEBUG,
1078 "No RR policy in grpclb instance %p. Adding to grpclb's pending "
1079 "picks",
1080 (void *)(glb_policy));
1081 }
David Garcia Quintas8aace512016-08-15 14:55:12 -07001082 add_pending_pick(&glb_policy->pending_picks, pick_args, target,
1083 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -07001084
1085 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001086 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001087 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001088 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001089 }
1090 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001091 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001092}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001093
David Garcia Quintas65318262016-07-29 13:43:38 -07001094static grpc_connectivity_state glb_check_connectivity(
1095 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1096 grpc_error **connectivity_error) {
1097 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1098 grpc_connectivity_state st;
1099 gpr_mu_lock(&glb_policy->mu);
Craig Tiller613dafa2017-02-09 12:00:43 -08001100 st = grpc_connectivity_state_get(&glb_policy->state_tracker,
1101 connectivity_error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001102 gpr_mu_unlock(&glb_policy->mu);
1103 return st;
1104}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001105
David Garcia Quintas65318262016-07-29 13:43:38 -07001106static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1107 grpc_closure *closure) {
1108 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1109 gpr_mu_lock(&glb_policy->mu);
1110 if (glb_policy->rr_policy) {
1111 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
1112 } else {
1113 add_pending_ping(&glb_policy->pending_pings, closure);
1114 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001115 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001116 }
1117 }
1118 gpr_mu_unlock(&glb_policy->mu);
1119}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001120
David Garcia Quintas65318262016-07-29 13:43:38 -07001121static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
1122 grpc_lb_policy *pol,
1123 grpc_connectivity_state *current,
1124 grpc_closure *notify) {
1125 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1126 gpr_mu_lock(&glb_policy->mu);
1127 grpc_connectivity_state_notify_on_state_change(
1128 exec_ctx, &glb_policy->state_tracker, current, notify);
1129
1130 gpr_mu_unlock(&glb_policy->mu);
1131}
1132
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001133static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
1134 grpc_error *error);
1135static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
1136 grpc_error *error);
Craig Tillerc5866662016-11-16 15:25:00 -08001137static void lb_call_init_locked(grpc_exec_ctx *exec_ctx,
1138 glb_lb_policy *glb_policy) {
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001139 GPR_ASSERT(glb_policy->server_name != NULL);
1140 GPR_ASSERT(glb_policy->server_name[0] != '\0');
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001141 GPR_ASSERT(!glb_policy->shutting_down);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001142
David Garcia Quintas15eba132016-08-09 15:20:48 -07001143 /* Note the following LB call progresses every time there's activity in \a
1144 * glb_policy->base.interested_parties, which is comprised of the polling
Yuchen Zengf7c45ae2016-09-15 13:40:32 -07001145 * entities from \a client_channel. */
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001146 grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001147 glb_policy->lb_call = grpc_channel_create_pollset_set_call(
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001148 exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -07001149 glb_policy->base.interested_parties,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001150 GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
1151 &host, glb_policy->deadline, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -07001152
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001153 grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
1154 grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001155
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001156 grpc_grpclb_request *request =
1157 grpc_grpclb_request_create(glb_policy->server_name);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001158 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001159 glb_policy->lb_request_payload =
David Garcia Quintas65318262016-07-29 13:43:38 -07001160 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001161 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
David Garcia Quintas65318262016-07-29 13:43:38 -07001162 grpc_grpclb_request_destroy(request);
1163
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001164 grpc_closure_init(&glb_policy->lb_on_server_status_received,
Craig Tiller91031da2016-12-28 15:44:25 -08001165 lb_on_server_status_received, glb_policy,
1166 grpc_schedule_on_exec_ctx);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001167 grpc_closure_init(&glb_policy->lb_on_response_received,
Craig Tiller91031da2016-12-28 15:44:25 -08001168 lb_on_response_received, glb_policy,
1169 grpc_schedule_on_exec_ctx);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001170
David Garcia Quintas1edfb952016-11-22 17:15:34 -08001171 gpr_backoff_init(&glb_policy->lb_call_backoff_state,
1172 GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS,
1173 GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER,
1174 GRPC_GRPCLB_RECONNECT_JITTER,
1175 GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000,
1176 GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
David Garcia Quintas65318262016-07-29 13:43:38 -07001177}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001178
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001179static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx,
1180 glb_lb_policy *glb_policy) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001181 GPR_ASSERT(glb_policy->lb_call != NULL);
1182 grpc_call_destroy(glb_policy->lb_call);
1183 glb_policy->lb_call = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -07001184
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001185 grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
1186 grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001187
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001188 grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001189 grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
David Garcia Quintas65318262016-07-29 13:43:38 -07001190}
1191
David Garcia Quintas8d489112016-07-29 15:20:42 -07001192/*
1193 * Auxiliary functions and LB client callbacks.
1194 */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001195static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
1196 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001197 GPR_ASSERT(glb_policy->lb_channel != NULL);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001198 if (glb_policy->shutting_down) return;
1199
Craig Tillerc5866662016-11-16 15:25:00 -08001200 lb_call_init_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001201
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001202 if (grpc_lb_glb_trace) {
1203 gpr_log(GPR_INFO, "Query for backends (grpclb: %p, lb_call: %p)",
1204 (void *)glb_policy, (void *)glb_policy->lb_call);
1205 }
1206 GPR_ASSERT(glb_policy->lb_call != NULL);
1207
David Garcia Quintas65318262016-07-29 13:43:38 -07001208 grpc_call_error call_error;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001209 grpc_op ops[4];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001210 memset(ops, 0, sizeof(ops));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001211
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001212 grpc_op *op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -07001213 op->op = GRPC_OP_SEND_INITIAL_METADATA;
1214 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001215 op->flags = 0;
1216 op->reserved = NULL;
1217 op++;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001218
1219 op->op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001220 op->data.recv_initial_metadata.recv_initial_metadata =
1221 &glb_policy->lb_initial_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001222 op->flags = 0;
1223 op->reserved = NULL;
1224 op++;
1225
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001226 GPR_ASSERT(glb_policy->lb_request_payload != NULL);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001227 op->op = GRPC_OP_SEND_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001228 op->data.send_message.send_message = glb_policy->lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001229 op->flags = 0;
1230 op->reserved = NULL;
1231 op++;
1232
1233 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1234 op->data.recv_status_on_client.trailing_metadata =
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001235 &glb_policy->lb_trailing_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001236 op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
1237 op->data.recv_status_on_client.status_details =
1238 &glb_policy->lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001239 op->flags = 0;
1240 op->reserved = NULL;
1241 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001242 /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
1243 * count goes to zero) to be unref'd in lb_on_server_status_received */
1244 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received");
David Garcia Quintas65318262016-07-29 13:43:38 -07001245 call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001246 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1247 &glb_policy->lb_on_server_status_received);
David Garcia Quintas65318262016-07-29 13:43:38 -07001248 GPR_ASSERT(GRPC_CALL_OK == call_error);
1249
1250 op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001251 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001252 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001253 op->flags = 0;
1254 op->reserved = NULL;
1255 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001256 /* take another weak ref to be unref'd in lb_on_response_received */
1257 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received");
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001258 call_error = grpc_call_start_batch_and_execute(
1259 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1260 &glb_policy->lb_on_response_received);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001261 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001262}
1263
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001264static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
1265 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001266 glb_lb_policy *glb_policy = arg;
1267
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001268 grpc_op ops[2];
1269 memset(ops, 0, sizeof(ops));
1270 grpc_op *op = ops;
David Garcia Quintasf9532952016-11-08 14:14:25 -08001271 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001272 if (glb_policy->lb_response_payload != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001273 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001274 /* Received data from the LB server. Look inside
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001275 * glb_policy->lb_response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001276 grpc_byte_buffer_reader bbr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001277 grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001278 grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001279 grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001280 grpc_grpclb_serverlist *serverlist =
1281 grpc_grpclb_response_parse_serverlist(response_slice);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001282 if (serverlist != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001283 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001284 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001285 if (grpc_lb_glb_trace) {
Jan Tattermusch2b398082016-10-07 14:40:30 +02001286 gpr_log(GPR_INFO, "Serverlist with %lu servers received",
1287 (unsigned long)serverlist->num_servers);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001288 for (size_t i = 0; i < serverlist->num_servers; ++i) {
1289 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001290 parse_server(serverlist->servers[i], &addr);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001291 char *ipport;
1292 grpc_sockaddr_to_string(&ipport, &addr, false);
1293 gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport);
1294 gpr_free(ipport);
1295 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001296 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001297
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001298 /* update serverlist */
1299 if (serverlist->num_servers > 0) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001300 if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001301 if (grpc_lb_glb_trace) {
1302 gpr_log(GPR_INFO,
1303 "Incoming server list identical to current, ignoring.");
1304 }
David Garcia Quintas1ebcaa22016-11-21 21:52:47 -08001305 grpc_grpclb_destroy_serverlist(serverlist);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001306 } else { /* new serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001307 if (glb_policy->serverlist != NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001308 /* dispose of the old serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001309 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001310 }
David Garcia Quintas1ebcaa22016-11-21 21:52:47 -08001311 /* and update the copy in the glb_lb_policy instance. This serverlist
1312 * instance will be destroyed either upon the next update or in
1313 * glb_destroy() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001314 glb_policy->serverlist = serverlist;
1315
David Garcia Quintas149f09d2016-11-17 20:43:10 -08001316 rr_handover_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001317 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001318 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001319 if (grpc_lb_glb_trace) {
1320 gpr_log(GPR_INFO,
1321 "Received empty server list. Picks will stay pending until a "
1322 "response with > 0 servers is received");
1323 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001324 }
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001325 } else { /* serverlist == NULL */
1326 gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.",
Craig Tiller32df4672016-11-04 08:21:56 -07001327 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
Craig Tiller18b4ba32016-11-09 15:23:42 -08001328 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001329 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001330
David Garcia Quintas246c5642016-11-01 11:16:52 -07001331 if (!glb_policy->shutting_down) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001332 /* keep listening for serverlist updates */
1333 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001334 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001335 op->flags = 0;
1336 op->reserved = NULL;
1337 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001338 /* reuse the "lb_on_response_received" weak ref taken in
1339 * query_for_backends_locked() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001340 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas246c5642016-11-01 11:16:52 -07001341 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1342 &glb_policy->lb_on_response_received); /* loop */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001343 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001344 }
David Garcia Quintasf9532952016-11-08 14:14:25 -08001345 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintase224a762016-11-01 13:00:58 -07001346 } else { /* empty payload: call cancelled. */
1347 /* dispose of the "lb_on_response_received" weak ref taken in
1348 * query_for_backends_locked() and reused in every reception loop */
David Garcia Quintasd4d2ece2016-11-08 14:38:12 -08001349 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintase224a762016-11-01 13:00:58 -07001350 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1351 "lb_on_response_received_empty_payload");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001352 }
1353}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001354
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001355static void lb_call_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
1356 grpc_error *error) {
1357 glb_lb_policy *glb_policy = arg;
1358 gpr_mu_lock(&glb_policy->mu);
1359
1360 if (!glb_policy->shutting_down) {
1361 if (grpc_lb_glb_trace) {
1362 gpr_log(GPR_INFO, "Restaring call to LB server (grpclb %p)",
1363 (void *)glb_policy);
1364 }
1365 GPR_ASSERT(glb_policy->lb_call == NULL);
1366 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001367 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001368 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001369 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1370 "grpclb_on_retry_timer");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001371}
1372
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001373static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
1374 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001375 glb_lb_policy *glb_policy = arg;
1376 gpr_mu_lock(&glb_policy->mu);
1377
1378 GPR_ASSERT(glb_policy->lb_call != NULL);
1379
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001380 if (grpc_lb_glb_trace) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001381 char *status_details =
1382 grpc_slice_to_c_string(glb_policy->lb_call_status_details);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001383 gpr_log(GPR_DEBUG,
1384 "Status from LB server received. Status = %d, Details = '%s', "
1385 "(call: %p)",
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001386 glb_policy->lb_call_status, status_details,
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001387 (void *)glb_policy->lb_call);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001388 gpr_free(status_details);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001389 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001390
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001391 /* We need to perform cleanups no matter what. */
1392 lb_call_destroy_locked(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001393
1394 if (!glb_policy->shutting_down) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001395 /* if we aren't shutting down, restart the LB client call after some time */
1396 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
1397 gpr_timespec next_try =
1398 gpr_backoff_step(&glb_policy->lb_call_backoff_state, now);
1399 if (grpc_lb_glb_trace) {
1400 gpr_log(GPR_DEBUG, "Connection to LB server lost (grpclb: %p)...",
1401 (void *)glb_policy);
1402 gpr_timespec timeout = gpr_time_sub(next_try, now);
1403 if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) {
1404 gpr_log(GPR_DEBUG, "... retrying in %" PRId64 ".%09d seconds.",
1405 timeout.tv_sec, timeout.tv_nsec);
1406 } else {
1407 gpr_log(GPR_DEBUG, "... retrying immediately.");
1408 }
1409 }
1410 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
Masood Malekghassemib5b43722017-01-05 15:07:26 -08001411 grpc_closure_init(&glb_policy->lb_on_call_retry, lb_call_on_retry_timer,
1412 glb_policy, grpc_schedule_on_exec_ctx);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001413 grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
Masood Malekghassemib5b43722017-01-05 15:07:26 -08001414 &glb_policy->lb_on_call_retry, now);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001415 }
1416 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001417 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1418 "lb_on_server_status_received");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001419}
1420
David Garcia Quintas8d489112016-07-29 15:20:42 -07001421/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001422static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
1423 glb_destroy, glb_shutdown, glb_pick,
1424 glb_cancel_pick, glb_cancel_picks, glb_ping_one,
1425 glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
1426
1427static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
1428
1429static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
1430
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001431static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1432 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1433
1434static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1435
1436grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
1437 return &glb_lb_policy_factory;
1438}
1439
1440/* Plugin registration */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001441void grpc_lb_policy_grpclb_init() {
1442 grpc_register_lb_policy(grpc_glb_lb_factory_create());
1443 grpc_register_tracer("glb", &grpc_lb_glb_trace);
1444}
1445
1446void grpc_lb_policy_grpclb_shutdown() {}