blob: e094fdc7996110c29595a704e03587efabc1f56c [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. Roth2137cd82016-09-14 09:04:00 -0700109#include "src/core/ext/client_channel/client_channel_factory.h"
Mark D. Roth15195742016-10-07 09:02:28 -0700110#include "src/core/ext/client_channel/lb_policy_factory.h"
Mark D. Roth2137cd82016-09-14 09:04:00 -0700111#include "src/core/ext/client_channel/lb_policy_registry.h"
112#include "src/core/ext/client_channel/parse_address.h"
David Garcia Quintas8782d1b2016-06-15 23:58:44 -0700113#include "src/core/ext/lb_policy/grpclb/grpclb.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700114#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
Mark D. Roth046cf762016-09-26 11:13:51 -0700115#include "src/core/lib/channel/channel_args.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200116#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700117#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200118#include "src/core/lib/iomgr/timer.h"
Craig Tiller0f310802016-10-26 16:25:56 -0700119#include "src/core/lib/slice/slice_string_helpers.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200120#include "src/core/lib/support/backoff.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700121#include "src/core/lib/support/string.h"
122#include "src/core/lib/surface/call.h"
123#include "src/core/lib/surface/channel.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700124#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700125
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200126#define BACKOFF_MULTIPLIER 1.6
127#define BACKOFF_JITTER 0.2
128#define BACKOFF_MIN_SECONDS 10
129#define BACKOFF_MAX_SECONDS 60
130
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700131int grpc_lb_glb_trace = 0;
132
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700133/* add lb_token of selected subchannel (address) to the call's initial
134 * metadata */
135static void initial_metadata_add_lb_token(
136 grpc_metadata_batch *initial_metadata,
137 grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem *lb_token) {
138 GPR_ASSERT(lb_token_mdelem_storage != NULL);
139 GPR_ASSERT(lb_token != NULL);
140 grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage,
141 lb_token);
142}
143
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700144typedef struct wrapped_rr_closure_arg {
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700145 /* the closure instance using this struct as argument */
146 grpc_closure wrapper_closure;
147
David Garcia Quintas43339842016-07-18 12:56:09 -0700148 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
149 * calls against the internal RR instance, respectively. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700150 grpc_closure *wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700151
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700152 /* the pick's initial metadata, kept in order to append the LB token for the
153 * pick */
154 grpc_metadata_batch *initial_metadata;
155
156 /* the picked target, used to determine which LB token to add to the pick's
157 * initial metadata */
158 grpc_connected_subchannel **target;
159
160 /* the LB token associated with the pick */
161 grpc_mdelem *lb_token;
162
163 /* storage for the lb token initial metadata mdelem */
164 grpc_linked_mdelem *lb_token_mdelem_storage;
165
David Garcia Quintas43339842016-07-18 12:56:09 -0700166 /* The RR instance related to the closure */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700167 grpc_lb_policy *rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700168
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700169 /* heap memory to be freed upon closure execution. */
170 void *free_when_done;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700171} wrapped_rr_closure_arg;
172
173/* The \a on_complete closure passed as part of the pick requires keeping a
174 * reference to its associated round robin instance. We wrap this closure in
175 * order to unref the round robin instance upon its invocation */
176static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700177 grpc_error *error) {
David Garcia Quintas43339842016-07-18 12:56:09 -0700178 wrapped_rr_closure_arg *wc_arg = arg;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700179
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200180 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
181 grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error),
182 NULL);
183
184 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700185 /* if target is NULL, no pick has been made by the RR policy (eg, all
186 * addresses failed to connect). There won't be any user_data/token
187 * available */
188 if (wc_arg->target != NULL) {
David Garcia Quintas80069492016-11-08 14:17:48 -0800189 GPR_ASSERT(wc_arg->lb_token != NULL);
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700190 initial_metadata_add_lb_token(wc_arg->initial_metadata,
191 wc_arg->lb_token_mdelem_storage,
192 GRPC_MDELEM_REF(wc_arg->lb_token));
193 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200194 if (grpc_lb_glb_trace) {
195 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
196 (intptr_t)wc_arg->rr_policy);
197 }
198 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700199 }
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700200 GPR_ASSERT(wc_arg->free_when_done != NULL);
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700201 gpr_free(wc_arg->free_when_done);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700202}
203
David Garcia Quintasea11d162016-07-14 17:27:28 -0700204/* Linked list of pending pick requests. It stores all information needed to
205 * eventually call (Round Robin's) pick() on them. They mainly stay pending
206 * waiting for the RR policy to be created/updated.
207 *
208 * One particularity is the wrapping of the user-provided \a on_complete closure
209 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
210 * order to correctly unref the RR policy instance upon completion of the pick.
211 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700212typedef struct pending_pick {
213 struct pending_pick *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700214
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700215 /* original pick()'s arguments */
216 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700217
218 /* output argument where to store the pick()ed connected subchannel, or NULL
219 * upon error. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700220 grpc_connected_subchannel **target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700221
David Garcia Quintas43339842016-07-18 12:56:09 -0700222 /* args for wrapped_on_complete */
223 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700224} pending_pick;
225
David Garcia Quintas8aace512016-08-15 14:55:12 -0700226static void add_pending_pick(pending_pick **root,
227 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas65318262016-07-29 13:43:38 -0700228 grpc_connected_subchannel **target,
229 grpc_closure *on_complete) {
230 pending_pick *pp = gpr_malloc(sizeof(*pp));
231 memset(pp, 0, sizeof(pending_pick));
232 memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
233 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700234 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700235 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700236 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700237 pp->wrapped_on_complete_arg.target = target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700238 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
239 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
240 pick_args->lb_token_mdelem_storage;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700241 pp->wrapped_on_complete_arg.free_when_done = pp;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700242 grpc_closure_init(&pp->wrapped_on_complete_arg.wrapper_closure,
243 wrapped_rr_closure, &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700244 *root = pp;
245}
246
David Garcia Quintasea11d162016-07-14 17:27:28 -0700247/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700248typedef struct pending_ping {
249 struct pending_ping *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700250
David Garcia Quintas43339842016-07-18 12:56:09 -0700251 /* args for wrapped_notify */
252 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700253} pending_ping;
254
David Garcia Quintas65318262016-07-29 13:43:38 -0700255static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
256 pending_ping *pping = gpr_malloc(sizeof(*pping));
257 memset(pping, 0, sizeof(pending_ping));
258 memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
David Garcia Quintas65318262016-07-29 13:43:38 -0700259 pping->wrapped_notify_arg.wrapped_closure = notify;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700260 pping->wrapped_notify_arg.free_when_done = pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700261 pping->next = *root;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700262 grpc_closure_init(&pping->wrapped_notify_arg.wrapper_closure,
263 wrapped_rr_closure, &pping->wrapped_notify_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700264 *root = pping;
265}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700266
David Garcia Quintas8d489112016-07-29 15:20:42 -0700267/*
268 * glb_lb_policy
269 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700270typedef struct rr_connectivity_data rr_connectivity_data;
David Garcia Quintas65318262016-07-29 13:43:38 -0700271static const grpc_lb_policy_vtable glb_lb_policy_vtable;
272typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700273 /** base policy: must be first */
274 grpc_lb_policy base;
275
276 /** mutex protecting remaining members */
277 gpr_mu mu;
278
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700279 /** who the client is trying to communicate with */
Mark D. Rothd1604af2016-09-22 11:20:27 -0700280 const char *server_name;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700281 grpc_client_channel_factory *cc_factory;
Mark D. Roth046cf762016-09-26 11:13:51 -0700282 grpc_channel_args *args;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700283
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700284 /** deadline for the LB's call */
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700285 gpr_timespec deadline;
286
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700287 /** for communicating with the LB server */
David Garcia Quintasea11d162016-07-14 17:27:28 -0700288 grpc_channel *lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700289
290 /** the RR policy to use of the backend servers returned by the LB server */
291 grpc_lb_policy *rr_policy;
292
293 bool started_picking;
294
295 /** our connectivity state tracker */
296 grpc_connectivity_state_tracker state_tracker;
297
David Garcia Quintasea11d162016-07-14 17:27:28 -0700298 /** stores the deserialized response from the LB. May be NULL until one such
299 * response has arrived. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700300 grpc_grpclb_serverlist *serverlist;
301
David Garcia Quintasea11d162016-07-14 17:27:28 -0700302 /** list of picks that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700303 pending_pick *pending_picks;
304
David Garcia Quintasea11d162016-07-14 17:27:28 -0700305 /** list of pings that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700306 pending_ping *pending_pings;
307
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200308 bool shutting_down;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700309
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200310 /************************************************************/
311 /* client data associated with the LB server communication */
312 /************************************************************/
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100313 /* Status from the LB server has been received. This signals the end of the LB
314 * call. */
315 grpc_closure lb_on_server_status_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200316
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100317 /* A response from the LB server has been received. Process it */
318 grpc_closure lb_on_response_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200319
320 grpc_call *lb_call; /* streaming call to the LB server, */
321
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100322 grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */
323 grpc_metadata_array
324 lb_trailing_metadata_recv; /* trailing MD from LB server */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200325
326 /* what's being sent to the LB server. Note that its value may vary if the LB
327 * server indicates a redirect. */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100328 grpc_byte_buffer *lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200329
David Garcia Quintas246c5642016-11-01 11:16:52 -0700330 /* response the LB server, if any. Processed in lb_on_response_received() */
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100331 grpc_byte_buffer *lb_response_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200332
David Garcia Quintas246c5642016-11-01 11:16:52 -0700333 /* call status code and details, set in lb_on_server_status_received() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200334 grpc_status_code lb_call_status;
335 char *lb_call_status_details;
336 size_t lb_call_status_details_capacity;
337
338 /** LB call retry backoff state */
339 gpr_backoff lb_call_backoff_state;
340
341 /** LB call retry timer */
342 grpc_timer lb_call_retry_timer;
David Garcia Quintas65318262016-07-29 13:43:38 -0700343} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700344
David Garcia Quintas65318262016-07-29 13:43:38 -0700345/* Keeps track and reacts to changes in connectivity of the RR instance */
346struct rr_connectivity_data {
347 grpc_closure on_change;
348 grpc_connectivity_state state;
349 glb_lb_policy *glb_policy;
350};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700351
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700352static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
353 bool log) {
354 const grpc_grpclb_ip_address *ip = &server->ip_address;
355 if (server->port >> 16 != 0) {
356 if (log) {
357 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200358 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
359 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700360 }
361 return false;
362 }
363
364 if (ip->size != 4 && ip->size != 16) {
365 if (log) {
366 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200367 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700368 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200369 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700370 }
371 return false;
372 }
373 return true;
374}
375
Mark D. Roth16883a32016-10-21 10:30:58 -0700376/* vtable for LB tokens in grpc_lb_addresses. */
Mark D. Roth557c9902016-10-24 11:12:05 -0700377static void *lb_token_copy(void *token) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700378 return token == NULL ? NULL : GRPC_MDELEM_REF(token);
379}
380static void lb_token_destroy(void *token) {
381 if (token != NULL) GRPC_MDELEM_UNREF(token);
382}
Mark D. Roth557c9902016-10-24 11:12:05 -0700383static int lb_token_cmp(void *token1, void *token2) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700384 if (token1 > token2) return 1;
385 if (token1 < token2) return -1;
386 return 0;
387}
388static const grpc_lb_user_data_vtable lb_token_vtable = {
389 lb_token_copy, lb_token_destroy, lb_token_cmp};
390
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100391static void parse_server(const grpc_grpclb_server *server,
392 grpc_resolved_address *addr) {
393 const uint16_t netorder_port = htons((uint16_t)server->port);
394 /* the addresses are given in binary format (a in(6)_addr struct) in
395 * server->ip_address.bytes. */
396 const grpc_grpclb_ip_address *ip = &server->ip_address;
397 memset(addr, 0, sizeof(*addr));
398 if (ip->size == 4) {
399 addr->len = sizeof(struct sockaddr_in);
400 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr->addr;
401 addr4->sin_family = AF_INET;
402 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
403 addr4->sin_port = netorder_port;
404 } else if (ip->size == 16) {
405 addr->len = sizeof(struct sockaddr_in6);
406 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr->addr;
David Garcia Quintas107ca162016-11-02 18:17:03 -0700407 addr6->sin6_family = AF_INET6;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100408 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
409 addr6->sin6_port = netorder_port;
410 }
411}
412
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700413/* Returns addresses extracted from \a serverlist. */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700414static grpc_lb_addresses *process_serverlist(
Mark D. Rothc5c38782016-09-16 08:51:01 -0700415 const grpc_grpclb_serverlist *serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700416 size_t num_valid = 0;
417 /* first pass: count how many are valid in order to allocate the necessary
418 * memory in a single block */
419 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700420 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700421 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700422 if (num_valid == 0) return NULL;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700423
Mark D. Roth16883a32016-10-21 10:30:58 -0700424 grpc_lb_addresses *lb_addresses =
425 grpc_lb_addresses_create(num_valid, &lb_token_vtable);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700426
427 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700428 * to the outside world) to be read by the RR policy during its creation.
429 * Given that the validity tests are very cheap, they are performed again
430 * instead of marking the valid ones during the first pass, as this would
431 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700432 size_t addr_idx = 0;
433 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
434 GPR_ASSERT(addr_idx < num_valid);
435 const grpc_grpclb_server *server = serverlist->servers[sl_idx];
436 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700437
438 /* address processing */
Mark D. Rothc5c38782016-09-16 08:51:01 -0700439 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100440 parse_server(server, &addr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700441
442 /* lb token processing */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700443 void *user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700444 if (server->has_load_balance_token) {
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200445 const size_t lb_token_max_length =
446 GPR_ARRAY_SIZE(server->load_balance_token);
447 const size_t lb_token_length =
448 strnlen(server->load_balance_token, lb_token_max_length);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700449 grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200450 (uint8_t *)server->load_balance_token, lb_token_length);
David Garcia Quintasa3654db2016-10-11 15:52:39 -0700451 user_data = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_LB_TOKEN,
452 lb_token_mdstr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700453 } else {
454 gpr_log(GPR_ERROR,
455 "Missing LB token for backend address '%s'. The empty token will "
456 "be used instead",
murgatroid9908b0fab2016-09-23 14:35:49 -0700457 grpc_sockaddr_to_uri(&addr));
David Garcia Quintasa3654db2016-10-11 15:52:39 -0700458 user_data = GRPC_MDELEM_LB_TOKEN_EMPTY;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700459 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700460
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700461 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
462 false /* is_balancer */,
Mark D. Rothc5c38782016-09-16 08:51:01 -0700463 NULL /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700464 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700465 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700466 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700467 return lb_addresses;
468}
469
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800470/* returns true if the new RR policy should replace the current one, if any */
471static bool update_lb_connectivity_status_locked(
472 grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
473 grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
474 grpc_error *curr_state_error;
475 const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check(
476 &glb_policy->state_tracker, &curr_state_error);
477
478 /* The new connectivity status is a function of the previous one and the new
479 * input coming from the status of the RR policy.
480 *
481 * old state (grpclb's)
482 * |
483 * v || I | C | R | TF | SD | <- new state (RR's)
484 * ===++====+=====+=====+======+======+
485 * I || I | C | R | I | I |
486 * ---++----+-----+-----+------+------+
487 * C || I | C | R | C | C |
488 * ---++----+-----+-----+------+------+
489 * R || I | C | R | R | R |
490 * ---++----+-----+-----+------+------+
491 * TF || I | C | R | TF | TF |
492 * ---++----+-----+-----+------+------+
493 * SD || NA | NA | NA | NA | NA | (*)
494 * ---++----+-----+-----+------+------+
495 *
496 * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
497 * the previous RR instance.
498 *
499 * Note that the status is never updated to SHUTDOWN as a result of calling
500 * this function. Only glb_shutdown() has the power to set that state.
501 *
502 * (*) This function mustn't be called during shutting down. */
503 GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
504
505 switch (new_rr_state) {
506 case GRPC_CHANNEL_TRANSIENT_FAILURE:
507 case GRPC_CHANNEL_SHUTDOWN:
508 GPR_ASSERT(new_rr_state_error != GRPC_ERROR_NONE);
509 return false; /* don't replace the RR policy */
510 case GRPC_CHANNEL_INIT:
511 case GRPC_CHANNEL_IDLE:
512 case GRPC_CHANNEL_CONNECTING:
513 case GRPC_CHANNEL_READY:
514 GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE);
515 }
516
517 if (grpc_lb_glb_trace) {
518 gpr_log(GPR_INFO,
519 "Setting grpclb's state to %s from new RR policy %p state.",
520 grpc_connectivity_state_name(new_rr_state),
521 (void *)glb_policy->rr_policy);
522 }
523 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
524 new_rr_state, GRPC_ERROR_REF(new_rr_state_error),
525 "update_lb_connectivity_status_locked");
526 return true;
527}
528
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700529/* perform a pick over \a rr_policy. Given that a pick can return immediately
530 * (ignoring its completion callback) we need to perform the cleanups this
531 * callback would be otherwise resposible for */
David Garcia Quintas20359062016-10-15 15:22:51 -0700532static bool pick_from_internal_rr_locked(
533 grpc_exec_ctx *exec_ctx, grpc_lb_policy *rr_policy,
534 const grpc_lb_policy_pick_args *pick_args,
535 grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) {
536 GPR_ASSERT(rr_policy != NULL);
537 const bool pick_done =
538 grpc_lb_policy_pick(exec_ctx, rr_policy, pick_args, target,
539 (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure);
540 if (pick_done) {
541 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
542 if (grpc_lb_glb_trace) {
543 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
544 (intptr_t)wc_arg->rr_policy);
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700545 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200546 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700547
David Garcia Quintas20359062016-10-15 15:22:51 -0700548 /* add the load reporting initial metadata */
549 initial_metadata_add_lb_token(pick_args->initial_metadata,
550 pick_args->lb_token_mdelem_storage,
551 GRPC_MDELEM_REF(wc_arg->lb_token));
552
553 gpr_free(wc_arg);
554 }
555 /* else, the pending pick will be registered and taken care of by the
556 * pending pick list inside the RR policy (glb_policy->rr_policy).
557 * Eventually, wrapped_on_complete will be called, which will -among other
558 * things- add the LB token to the call's initial metadata */
David Garcia Quintas20359062016-10-15 15:22:51 -0700559 return pick_done;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700560}
561
David Garcia Quintas90712d52016-10-13 19:33:04 -0700562static grpc_lb_policy *create_rr_locked(
563 grpc_exec_ctx *exec_ctx, const grpc_grpclb_serverlist *serverlist,
564 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700565 GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700566
567 grpc_lb_policy_args args;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700568 memset(&args, 0, sizeof(args));
David Garcia Quintas65318262016-07-29 13:43:38 -0700569 args.client_channel_factory = glb_policy->cc_factory;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200570 grpc_lb_addresses *addresses = process_serverlist(serverlist);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700571
572 // Replace the LB addresses in the channel args that we pass down to
573 // the subchannel.
Mark D. Roth557c9902016-10-24 11:12:05 -0700574 static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200575 const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700576 args.args = grpc_channel_args_copy_and_add_and_remove(
577 glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
578 1);
David Garcia Quintas65318262016-07-29 13:43:38 -0700579
580 grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200581 GPR_ASSERT(rr != NULL);
582 grpc_lb_addresses_destroy(addresses);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700583 grpc_channel_args_destroy(args.args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700584 return rr;
585}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700586
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200587static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
588 grpc_error *error);
589/* glb_policy->rr_policy may be NULL (initial handover) */
David Garcia Quintas90712d52016-10-13 19:33:04 -0700590static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800591 glb_lb_policy *glb_policy) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700592 GPR_ASSERT(glb_policy->serverlist != NULL &&
593 glb_policy->serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700594
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800595 if (glb_policy->shutting_down) return;
596
597 grpc_lb_policy *old_rr_policy = glb_policy->rr_policy;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200598
599 glb_policy->rr_policy =
600 create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800601 if (glb_policy->rr_policy == NULL) {
602 gpr_log(GPR_ERROR,
603 "Failure creating a RoundRobin policy for serverlist update with "
604 "%lu entries. The previous RR instance (%p), if any, will continue "
605 "to be used. Future updates from the LB will attempt to create new "
606 "instances.",
607 (unsigned long)glb_policy->serverlist->num_servers,
608 (void *)old_rr_policy);
609 /* restore the old policy */
610 glb_policy->rr_policy = old_rr_policy;
611 return;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200612 }
613
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800614 grpc_error *new_rr_state_error = NULL;
615 const grpc_connectivity_state new_rr_state =
616 grpc_lb_policy_check_connectivity(exec_ctx, glb_policy->rr_policy,
617 &new_rr_state_error);
618 /* Connectivity state is a function of the new RR policy just created */
619 const bool replace_old_rr = update_lb_connectivity_status_locked(
620 exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
621
622 if (!replace_old_rr) {
623 /* dispose of the new RR policy that won't be used after all */
624 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy,
625 "rr_handover_no_replace");
626 /* restore the old policy */
627 glb_policy->rr_policy = old_rr_policy;
628 return;
629 }
630
631 if (grpc_lb_glb_trace) {
632 gpr_log(GPR_INFO, "Created RR policy (%p)", (void *)glb_policy->rr_policy);
633 gpr_log(GPR_INFO, "RR handover. Old RR: %p", (void *)glb_policy->rr_policy);
634 }
635
636 if (old_rr_policy != NULL) {
637 /* if we are phasing out an existing RR instance, unref it. */
638 GRPC_LB_POLICY_UNREF(exec_ctx, old_rr_policy, "rr_handover");
639 }
640
641 /* Add the gRPC LB's interested_parties pollset_set to that of the newly
642 * created RR policy. This will make the RR policy progress upon activity on
643 * gRPC LB, which in turn is tied to the application's call */
Yuchen Zengb4291642016-09-01 19:17:14 -0700644 grpc_pollset_set_add_pollset_set(exec_ctx,
645 glb_policy->rr_policy->interested_parties,
646 glb_policy->base.interested_parties);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200647
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800648 /* Allocate the data for the tracking of the new RR policy's connectivity.
649 * It'll be deallocated in glb_rr_connectivity_changed() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200650 rr_connectivity_data *rr_connectivity =
651 gpr_malloc(sizeof(rr_connectivity_data));
652 memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
653 grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
654 rr_connectivity);
655 rr_connectivity->glb_policy = glb_policy;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800656 rr_connectivity->state = new_rr_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200657
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800658 /* Subscribe to changes to the connectivity of the new RR */
David Garcia Quintase224a762016-11-01 13:00:58 -0700659 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200660 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
661 &rr_connectivity->state,
662 &rr_connectivity->on_change);
David Garcia Quintas65318262016-07-29 13:43:38 -0700663 grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
664
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800665 /* Update picks and pings in wait */
David Garcia Quintas65318262016-07-29 13:43:38 -0700666 pending_pick *pp;
667 while ((pp = glb_policy->pending_picks)) {
668 glb_policy->pending_picks = pp->next;
669 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
670 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
671 if (grpc_lb_glb_trace) {
672 gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
673 (intptr_t)glb_policy->rr_policy);
674 }
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700675 pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
676 &pp->pick_args, pp->target,
677 &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700678 }
679
680 pending_ping *pping;
681 while ((pping = glb_policy->pending_pings)) {
682 glb_policy->pending_pings = pping->next;
683 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
684 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
685 if (grpc_lb_glb_trace) {
686 gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
687 (intptr_t)glb_policy->rr_policy);
688 }
689 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700690 &pping->wrapped_notify_arg.wrapper_closure);
David Garcia Quintas65318262016-07-29 13:43:38 -0700691 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700692}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700693
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700694static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
695 grpc_error *error) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800696 rr_connectivity_data *rr_connectivity = arg;
697 glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700698
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800699 gpr_mu_lock(&glb_policy->mu);
700 const bool shutting_down = glb_policy->shutting_down;
701 grpc_lb_policy *maybe_unref = NULL;
702 GRPC_ERROR_REF(error);
703
704 if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) {
705 /* RR policy shutting down. Don't renew subscription and free the arg of
706 * this callback. In addition we need to stash away the current policy to
707 * be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last
708 * one, the policy would be destroyed, alongside the lock, which would
709 * result in a use-after-free */
710 maybe_unref = &glb_policy->base;
711 gpr_free(rr_connectivity);
712 } else { /* rr state != SHUTDOWN && !shutting down: biz as usual */
713 update_lb_connectivity_status_locked(exec_ctx, glb_policy,
714 rr_connectivity->state, error);
715 /* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200716 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800717 &rr_connectivity->state,
718 &rr_connectivity->on_change);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700719 }
David Garcia Quintasf9532952016-11-08 14:14:25 -0800720 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800721 if (maybe_unref != NULL) {
722 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, maybe_unref, "rr_connectivity_cb");
723 }
724 GRPC_ERROR_UNREF(error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700725}
726
David Garcia Quintas65318262016-07-29 13:43:38 -0700727static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
728 grpc_lb_policy_factory *factory,
729 grpc_lb_policy_args *args) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700730 /* Get server name. */
Mark D. Roth557c9902016-10-24 11:12:05 -0700731 const grpc_arg *arg =
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700732 grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
Mark D. Roth557c9902016-10-24 11:12:05 -0700733 const char *server_name =
734 arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700735
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700736 /* Count the number of gRPC-LB addresses. There must be at least one.
737 * TODO(roth): For now, we ignore non-balancer addresses, but in the
738 * future, we may change the behavior such that we fall back to using
739 * the non-balancer addresses if we cannot reach any balancers. At that
740 * time, this should be changed to allow a list with no balancer addresses,
741 * since the resolver might fail to return a balancer address even when
742 * this is the right LB policy to use. */
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700743 arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
744 GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700745 grpc_lb_addresses *addresses = arg->value.pointer.p;
Mark D. Rothf655c852016-09-06 10:40:38 -0700746 size_t num_grpclb_addrs = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700747 for (size_t i = 0; i < addresses->num_addresses; ++i) {
748 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
Mark D. Rothf655c852016-09-06 10:40:38 -0700749 }
750 if (num_grpclb_addrs == 0) return NULL;
751
David Garcia Quintas65318262016-07-29 13:43:38 -0700752 glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
753 memset(glb_policy, 0, sizeof(*glb_policy));
754
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700755 /* All input addresses in addresses come from a resolver that claims
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700756 * they are LB services. It's the resolver's responsibility to make sure
757 * this
David Garcia Quintas65318262016-07-29 13:43:38 -0700758 * policy is only instantiated and used in that case.
759 *
760 * Create a client channel over them to communicate with a LB service */
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700761 glb_policy->server_name = gpr_strdup(server_name);
David Garcia Quintas65318262016-07-29 13:43:38 -0700762 glb_policy->cc_factory = args->client_channel_factory;
Mark D. Roth98abfd32016-10-21 08:10:51 -0700763 glb_policy->args = grpc_channel_args_copy(args->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700764 GPR_ASSERT(glb_policy->cc_factory != NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700765
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700766 /* construct a target from the addresses in args, given in the form
David Garcia Quintas65318262016-07-29 13:43:38 -0700767 * ipvX://ip1:port1,ip2:port2,...
768 * TODO(dgq): support mixed ip version */
Mark D. Rothf655c852016-09-06 10:40:38 -0700769 char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700770 size_t addr_index = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700771 for (size_t i = 0; i < addresses->num_addresses; i++) {
772 if (addresses->addresses[i].user_data != NULL) {
David Garcia Quintas5ebb7af2016-09-15 10:02:16 -0700773 gpr_log(GPR_ERROR,
774 "This LB policy doesn't support user data. It will be ignored");
775 }
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700776 if (addresses->addresses[i].is_balancer) {
Mark D. Rothc5c38782016-09-16 08:51:01 -0700777 if (addr_index == 0) {
murgatroid99dedb9232016-09-26 13:54:04 -0700778 addr_strs[addr_index++] =
Mark D. Rothfb809b72016-10-26 09:12:25 -0700779 grpc_sockaddr_to_uri(&addresses->addresses[i].address);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700780 } else {
Mark D. Roth49f89f02016-10-26 11:16:59 -0700781 GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
782 &addresses->addresses[i].address,
783 true) > 0);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700784 }
Mark D. Rothf655c852016-09-06 10:40:38 -0700785 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700786 }
787 size_t uri_path_len;
Mark D. Roth989cdcd2016-09-06 13:28:28 -0700788 char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
789 num_grpclb_addrs, ",", &uri_path_len);
David Garcia Quintas65318262016-07-29 13:43:38 -0700790
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700791 /* Create a channel to talk to the LBs.
792 *
793 * We strip out the channel arg for the LB policy name, since we want
794 * to use the default (pick_first) in this case.
795 *
796 * We also strip out the channel arg for the resolved addresses, since
797 * that will be generated by the name resolver used in the LB channel.
798 * Note that the LB channel will use the sockaddr resolver, so this
799 * won't actually generate a query to DNS (or some other name service).
800 * However, the addresses returned by the sockaddr resolver will have
801 * is_balancer=false, whereas our own addresses have is_balancer=true.
802 * We need the LB channel to return addresses with is_balancer=false
803 * so that it does not wind up recursively using the grpclb LB policy,
804 * as per the special case logic in client_channel.c.
805 */
Mark D. Roth557c9902016-10-24 11:12:05 -0700806 static const char *keys_to_remove[] = {GRPC_ARG_LB_POLICY_NAME,
807 GRPC_ARG_LB_ADDRESSES};
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700808 grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
809 args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
David Garcia Quintas65318262016-07-29 13:43:38 -0700810 glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
811 exec_ctx, glb_policy->cc_factory, target_uri_str,
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700812 GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
813 grpc_channel_args_destroy(new_args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700814
815 gpr_free(target_uri_str);
Mark D. Rothf655c852016-09-06 10:40:38 -0700816 for (size_t i = 0; i < num_grpclb_addrs; i++) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700817 gpr_free(addr_strs[i]);
818 }
819 gpr_free(addr_strs);
820
821 if (glb_policy->lb_channel == NULL) {
822 gpr_free(glb_policy);
823 return NULL;
824 }
825
David Garcia Quintas65318262016-07-29 13:43:38 -0700826 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
827 gpr_mu_init(&glb_policy->mu);
828 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
829 "grpclb");
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200830
David Garcia Quintas65318262016-07-29 13:43:38 -0700831 return &glb_policy->base;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700832}
833
David Garcia Quintas65318262016-07-29 13:43:38 -0700834static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
835 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
836 GPR_ASSERT(glb_policy->pending_picks == NULL);
837 GPR_ASSERT(glb_policy->pending_pings == NULL);
Mark D. Rothd1604af2016-09-22 11:20:27 -0700838 gpr_free((void *)glb_policy->server_name);
Mark D. Roth046cf762016-09-26 11:13:51 -0700839 grpc_channel_args_destroy(glb_policy->args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700840 grpc_channel_destroy(glb_policy->lb_channel);
841 glb_policy->lb_channel = NULL;
842 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
843 if (glb_policy->serverlist != NULL) {
844 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
845 }
846 gpr_mu_destroy(&glb_policy->mu);
847 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700848}
849
David Garcia Quintas65318262016-07-29 13:43:38 -0700850static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
851 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
852 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200853 glb_policy->shutting_down = true;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700854
David Garcia Quintas65318262016-07-29 13:43:38 -0700855 pending_pick *pp = glb_policy->pending_picks;
856 glb_policy->pending_picks = NULL;
857 pending_ping *pping = glb_policy->pending_pings;
858 glb_policy->pending_pings = NULL;
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800859 if (glb_policy->rr_policy) {
860 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
861 }
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -0800862 grpc_connectivity_state_set(
863 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
864 GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown");
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800865 /* We need a copy of the lb_call pointer because we can't cancell the call
866 * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
867 * the cancel, needs to acquire that same lock */
868 grpc_call *lb_call = glb_policy->lb_call;
David Garcia Quintas65318262016-07-29 13:43:38 -0700869 gpr_mu_unlock(&glb_policy->mu);
870
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800871 /* glb_policy->lb_call and this local lb_call must be consistent at this point
872 * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
873 * of query_for_backends_locked, which can only be invoked while
874 * glb_policy->shutting_down is false. */
875 if (lb_call != NULL) {
876 grpc_call_cancel(lb_call, NULL);
877 /* lb_on_server_status_received will pick up the cancel and clean up */
878 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700879 while (pp != NULL) {
880 pending_pick *next = pp->next;
881 *pp->target = NULL;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700882 grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
883 GRPC_ERROR_NONE, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700884 pp = next;
885 }
886
887 while (pping != NULL) {
888 pending_ping *next = pping->next;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700889 grpc_exec_ctx_sched(exec_ctx, &pping->wrapped_notify_arg.wrapper_closure,
890 GRPC_ERROR_NONE, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700891 pping = next;
892 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700893}
894
895static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
Mark D. Roth5f844002016-09-08 08:20:53 -0700896 grpc_connected_subchannel **target,
897 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700898 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
899 gpr_mu_lock(&glb_policy->mu);
900 pending_pick *pp = glb_policy->pending_picks;
901 glb_policy->pending_picks = NULL;
902 while (pp != NULL) {
903 pending_pick *next = pp->next;
904 if (pp->target == target) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700905 *target = NULL;
Mark D. Roth932b10c2016-09-09 08:44:30 -0700906 grpc_exec_ctx_sched(
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700907 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
Mark D. Roth932b10c2016-09-09 08:44:30 -0700908 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700909 } else {
910 pp->next = glb_policy->pending_picks;
911 glb_policy->pending_picks = pp;
912 }
913 pp = next;
914 }
915 gpr_mu_unlock(&glb_policy->mu);
Mark D. Roth5f844002016-09-08 08:20:53 -0700916 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700917}
918
David Garcia Quintas65318262016-07-29 13:43:38 -0700919static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
920 uint32_t initial_metadata_flags_mask,
Mark D. Rothe65ff112016-09-09 13:48:38 -0700921 uint32_t initial_metadata_flags_eq,
922 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700923 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
924 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas65318262016-07-29 13:43:38 -0700925 pending_pick *pp = glb_policy->pending_picks;
926 glb_policy->pending_picks = NULL;
927 while (pp != NULL) {
928 pending_pick *next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700929 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -0700930 initial_metadata_flags_eq) {
Mark D. Roth58f52b72016-09-09 13:55:18 -0700931 grpc_exec_ctx_sched(
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700932 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700933 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700934 } else {
935 pp->next = glb_policy->pending_picks;
936 glb_policy->pending_picks = pp;
937 }
938 pp = next;
939 }
940 gpr_mu_unlock(&glb_policy->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700941 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700942}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700943
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200944static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
945 glb_lb_policy *glb_policy);
946static void start_picking_locked(grpc_exec_ctx *exec_ctx,
947 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700948 glb_policy->started_picking = true;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200949 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
950 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700951}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700952
David Garcia Quintas65318262016-07-29 13:43:38 -0700953static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
954 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
955 gpr_mu_lock(&glb_policy->mu);
956 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200957 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700958 }
959 gpr_mu_unlock(&glb_policy->mu);
960}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700961
David Garcia Quintas65318262016-07-29 13:43:38 -0700962static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
David Garcia Quintas8aace512016-08-15 14:55:12 -0700963 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700964 grpc_connected_subchannel **target, void **user_data,
David Garcia Quintas65318262016-07-29 13:43:38 -0700965 grpc_closure *on_complete) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700966 if (pick_args->lb_token_mdelem_storage == NULL) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700967 *target = NULL;
David Garcia Quintas6cc44fc2016-09-12 23:04:35 -0700968 grpc_exec_ctx_sched(
969 exec_ctx, on_complete,
970 GRPC_ERROR_CREATE("No mdelem storage for the LB token. Load reporting "
971 "won't work without it. Failing"),
972 NULL);
Mark D. Roth1e5f6af2016-10-07 08:32:58 -0700973 return 0;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700974 }
975
David Garcia Quintas65318262016-07-29 13:43:38 -0700976 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
977 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700978 glb_policy->deadline = pick_args->deadline;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700979 bool pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -0700980
981 if (glb_policy->rr_policy != NULL) {
982 if (grpc_lb_glb_trace) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200983 gpr_log(GPR_INFO, "grpclb %p about to PICK from RR %p",
984 (void *)glb_policy, (void *)glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700985 }
986 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
David Garcia Quintas8aace512016-08-15 14:55:12 -0700987
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700988 wrapped_rr_closure_arg *wc_arg = gpr_malloc(sizeof(wrapped_rr_closure_arg));
David Garcia Quintas90712d52016-10-13 19:33:04 -0700989 memset(wc_arg, 0, sizeof(wrapped_rr_closure_arg));
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700990
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700991 grpc_closure_init(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg);
David Garcia Quintas90712d52016-10-13 19:33:04 -0700992 wc_arg->rr_policy = glb_policy->rr_policy;
993 wc_arg->target = target;
994 wc_arg->wrapped_closure = on_complete;
995 wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
996 wc_arg->initial_metadata = pick_args->initial_metadata;
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700997 wc_arg->free_when_done = wc_arg;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700998 pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy,
David Garcia Quintas20359062016-10-15 15:22:51 -0700999 pick_args, target, wc_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -07001000 } else {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001001 if (grpc_lb_glb_trace) {
1002 gpr_log(GPR_DEBUG,
1003 "No RR policy in grpclb instance %p. Adding to grpclb's pending "
1004 "picks",
1005 (void *)(glb_policy));
1006 }
David Garcia Quintas8aace512016-08-15 14:55:12 -07001007 add_pending_pick(&glb_policy->pending_picks, pick_args, target,
1008 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -07001009
1010 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001011 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001012 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001013 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001014 }
1015 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001016 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001017}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001018
David Garcia Quintas65318262016-07-29 13:43:38 -07001019static grpc_connectivity_state glb_check_connectivity(
1020 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1021 grpc_error **connectivity_error) {
1022 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1023 grpc_connectivity_state st;
1024 gpr_mu_lock(&glb_policy->mu);
1025 st = grpc_connectivity_state_check(&glb_policy->state_tracker,
1026 connectivity_error);
1027 gpr_mu_unlock(&glb_policy->mu);
1028 return st;
1029}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001030
David Garcia Quintas65318262016-07-29 13:43:38 -07001031static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
1032 grpc_closure *closure) {
1033 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1034 gpr_mu_lock(&glb_policy->mu);
1035 if (glb_policy->rr_policy) {
1036 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
1037 } else {
1038 add_pending_ping(&glb_policy->pending_pings, closure);
1039 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001040 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001041 }
1042 }
1043 gpr_mu_unlock(&glb_policy->mu);
1044}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001045
David Garcia Quintas65318262016-07-29 13:43:38 -07001046static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
1047 grpc_lb_policy *pol,
1048 grpc_connectivity_state *current,
1049 grpc_closure *notify) {
1050 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
1051 gpr_mu_lock(&glb_policy->mu);
1052 grpc_connectivity_state_notify_on_state_change(
1053 exec_ctx, &glb_policy->state_tracker, current, notify);
1054
1055 gpr_mu_unlock(&glb_policy->mu);
1056}
1057
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001058static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
1059 grpc_error *error);
1060static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
1061 grpc_error *error);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001062static void lb_call_init_locked(glb_lb_policy *glb_policy) {
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001063 GPR_ASSERT(glb_policy->server_name != NULL);
1064 GPR_ASSERT(glb_policy->server_name[0] != '\0');
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001065 GPR_ASSERT(!glb_policy->shutting_down);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001066
David Garcia Quintas15eba132016-08-09 15:20:48 -07001067 /* Note the following LB call progresses every time there's activity in \a
1068 * glb_policy->base.interested_parties, which is comprised of the polling
Yuchen Zengf7c45ae2016-09-15 13:40:32 -07001069 * entities from \a client_channel. */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001070 glb_policy->lb_call = grpc_channel_create_pollset_set_call(
David Garcia Quintas65318262016-07-29 13:43:38 -07001071 glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -07001072 glb_policy->base.interested_parties,
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001073 "/grpc.lb.v1.LoadBalancer/BalanceLoad", glb_policy->server_name,
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001074 glb_policy->deadline, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -07001075
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001076 grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
1077 grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001078
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001079 grpc_grpclb_request *request =
1080 grpc_grpclb_request_create(glb_policy->server_name);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001081 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001082 glb_policy->lb_request_payload =
David Garcia Quintas65318262016-07-29 13:43:38 -07001083 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001084 grpc_slice_unref(request_payload_slice);
David Garcia Quintas65318262016-07-29 13:43:38 -07001085 grpc_grpclb_request_destroy(request);
1086
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001087 glb_policy->lb_call_status_details = NULL;
1088 glb_policy->lb_call_status_details_capacity = 0;
1089
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001090 grpc_closure_init(&glb_policy->lb_on_server_status_received,
1091 lb_on_server_status_received, glb_policy);
1092 grpc_closure_init(&glb_policy->lb_on_response_received,
1093 lb_on_response_received, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001094
1095 gpr_backoff_init(&glb_policy->lb_call_backoff_state, BACKOFF_MULTIPLIER,
1096 BACKOFF_JITTER, BACKOFF_MIN_SECONDS * 1000,
1097 BACKOFF_MAX_SECONDS * 1000);
David Garcia Quintas65318262016-07-29 13:43:38 -07001098}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001099
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -08001100static void lb_call_destroy_locked(glb_lb_policy *glb_policy) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001101 GPR_ASSERT(glb_policy->lb_call != NULL);
1102 grpc_call_destroy(glb_policy->lb_call);
1103 glb_policy->lb_call = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -07001104
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001105 grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
1106 grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001107
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001108 grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001109 gpr_free(glb_policy->lb_call_status_details);
David Garcia Quintas65318262016-07-29 13:43:38 -07001110}
1111
David Garcia Quintas8d489112016-07-29 15:20:42 -07001112/*
1113 * Auxiliary functions and LB client callbacks.
1114 */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001115static void query_for_backends_locked(grpc_exec_ctx *exec_ctx,
1116 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001117 GPR_ASSERT(glb_policy->lb_channel != NULL);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001118 if (glb_policy->shutting_down) return;
1119
1120 lb_call_init_locked(glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001121
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001122 if (grpc_lb_glb_trace) {
1123 gpr_log(GPR_INFO, "Query for backends (grpclb: %p, lb_call: %p)",
1124 (void *)glb_policy, (void *)glb_policy->lb_call);
1125 }
1126 GPR_ASSERT(glb_policy->lb_call != NULL);
1127
David Garcia Quintas65318262016-07-29 13:43:38 -07001128 grpc_call_error call_error;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001129 grpc_op ops[4];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001130 memset(ops, 0, sizeof(ops));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001131
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001132 grpc_op *op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -07001133 op->op = GRPC_OP_SEND_INITIAL_METADATA;
1134 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001135 op->flags = 0;
1136 op->reserved = NULL;
1137 op++;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001138
1139 op->op = GRPC_OP_RECV_INITIAL_METADATA;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001140 op->data.recv_initial_metadata = &glb_policy->lb_initial_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001141 op->flags = 0;
1142 op->reserved = NULL;
1143 op++;
1144
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001145 GPR_ASSERT(glb_policy->lb_request_payload != NULL);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001146 op->op = GRPC_OP_SEND_MESSAGE;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001147 op->data.send_message = glb_policy->lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001148 op->flags = 0;
1149 op->reserved = NULL;
1150 op++;
1151
1152 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1153 op->data.recv_status_on_client.trailing_metadata =
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001154 &glb_policy->lb_trailing_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001155 op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
1156 op->data.recv_status_on_client.status_details =
1157 &glb_policy->lb_call_status_details;
1158 op->data.recv_status_on_client.status_details_capacity =
1159 &glb_policy->lb_call_status_details_capacity;
1160 op->flags = 0;
1161 op->reserved = NULL;
1162 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001163 /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
1164 * count goes to zero) to be unref'd in lb_on_server_status_received */
1165 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received");
David Garcia Quintas65318262016-07-29 13:43:38 -07001166 call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001167 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1168 &glb_policy->lb_on_server_status_received);
David Garcia Quintas65318262016-07-29 13:43:38 -07001169 GPR_ASSERT(GRPC_CALL_OK == call_error);
1170
1171 op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001172 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001173 op->data.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001174 op->flags = 0;
1175 op->reserved = NULL;
1176 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001177 /* take another weak ref to be unref'd in lb_on_response_received */
1178 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received");
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001179 call_error = grpc_call_start_batch_and_execute(
1180 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1181 &glb_policy->lb_on_response_received);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001182 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001183}
1184
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001185static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
1186 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001187 glb_lb_policy *glb_policy = arg;
1188
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001189 grpc_op ops[2];
1190 memset(ops, 0, sizeof(ops));
1191 grpc_op *op = ops;
David Garcia Quintasf9532952016-11-08 14:14:25 -08001192 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001193 if (glb_policy->lb_response_payload != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001194 gpr_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001195 /* Received data from the LB server. Look inside
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001196 * glb_policy->lb_response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001197 grpc_byte_buffer_reader bbr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001198 grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001199 grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001200 grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001201 grpc_grpclb_serverlist *serverlist =
1202 grpc_grpclb_response_parse_serverlist(response_slice);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001203 if (serverlist != NULL) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001204 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001205 grpc_slice_unref(response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001206 if (grpc_lb_glb_trace) {
Jan Tattermusch2b398082016-10-07 14:40:30 +02001207 gpr_log(GPR_INFO, "Serverlist with %lu servers received",
1208 (unsigned long)serverlist->num_servers);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001209 for (size_t i = 0; i < serverlist->num_servers; ++i) {
1210 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001211 parse_server(serverlist->servers[i], &addr);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001212 char *ipport;
1213 grpc_sockaddr_to_string(&ipport, &addr, false);
1214 gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport);
1215 gpr_free(ipport);
1216 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001217 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001218
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001219 /* update serverlist */
1220 if (serverlist->num_servers > 0) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001221 if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001222 if (grpc_lb_glb_trace) {
1223 gpr_log(GPR_INFO,
1224 "Incoming server list identical to current, ignoring.");
1225 }
1226 } else { /* new serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001227 if (glb_policy->serverlist != NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001228 /* dispose of the old serverlist */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001229 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001230 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001231 /* and update the copy in the glb_lb_policy instance */
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001232 glb_policy->serverlist = serverlist;
1233
David Garcia Quintas149f09d2016-11-17 20:43:10 -08001234 rr_handover_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001235 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001236 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001237 if (grpc_lb_glb_trace) {
1238 gpr_log(GPR_INFO,
1239 "Received empty server list. Picks will stay pending until a "
1240 "response with > 0 servers is received");
1241 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001242 }
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001243 } else { /* serverlist == NULL */
1244 gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.",
Craig Tiller32df4672016-11-04 08:21:56 -07001245 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
1246 grpc_slice_unref(response_slice);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001247 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001248
David Garcia Quintas246c5642016-11-01 11:16:52 -07001249 if (!glb_policy->shutting_down) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001250 /* keep listening for serverlist updates */
1251 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas246c5642016-11-01 11:16:52 -07001252 op->data.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 /* reuse the "lb_on_response_received" weak ref taken in
1257 * query_for_backends_locked() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001258 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas246c5642016-11-01 11:16:52 -07001259 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1260 &glb_policy->lb_on_response_received); /* loop */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001261 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001262 }
David Garcia Quintasf9532952016-11-08 14:14:25 -08001263 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintase224a762016-11-01 13:00:58 -07001264 } else { /* empty payload: call cancelled. */
murgatroid992e012342016-11-10 18:24:08 -08001265 /* dispose of the "lb_on_response_received" weak ref taken in
1266 * query_for_backends_locked() and reused in every reception loop */
David Garcia Quintasd4d2ece2016-11-08 14:38:12 -08001267 gpr_mu_unlock(&glb_policy->mu);
1268 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1269 "lb_on_response_received_empty_payload");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001270 }
1271}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001272
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001273static void lb_call_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
1274 grpc_error *error) {
1275 glb_lb_policy *glb_policy = arg;
1276 gpr_mu_lock(&glb_policy->mu);
1277
1278 if (!glb_policy->shutting_down) {
1279 if (grpc_lb_glb_trace) {
1280 gpr_log(GPR_INFO, "Restaring call to LB server (grpclb %p)",
1281 (void *)glb_policy);
1282 }
1283 GPR_ASSERT(glb_policy->lb_call == NULL);
1284 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001285 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001286 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001287 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1288 "grpclb_on_retry_timer");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001289}
1290
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001291static void lb_on_server_status_received(grpc_exec_ctx *exec_ctx, void *arg,
1292 grpc_error *error) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001293 glb_lb_policy *glb_policy = arg;
1294 gpr_mu_lock(&glb_policy->mu);
1295
1296 GPR_ASSERT(glb_policy->lb_call != NULL);
1297
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001298 if (grpc_lb_glb_trace) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001299 gpr_log(GPR_DEBUG,
1300 "Status from LB server received. Status = %d, Details = '%s', "
1301 "(call: %p)",
1302 glb_policy->lb_call_status, glb_policy->lb_call_status_details,
1303 (void *)glb_policy->lb_call);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001304 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001305
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001306 /* We need to performe cleanups no matter what. */
David Garcia Quintasaa24e9a2016-11-07 11:05:50 -08001307 lb_call_destroy_locked(glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001308
1309 if (!glb_policy->shutting_down) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001310 /* if we aren't shutting down, restart the LB client call after some time */
1311 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
1312 gpr_timespec next_try =
1313 gpr_backoff_step(&glb_policy->lb_call_backoff_state, now);
1314 if (grpc_lb_glb_trace) {
1315 gpr_log(GPR_DEBUG, "Connection to LB server lost (grpclb: %p)...",
1316 (void *)glb_policy);
1317 gpr_timespec timeout = gpr_time_sub(next_try, now);
1318 if (gpr_time_cmp(timeout, gpr_time_0(timeout.clock_type)) > 0) {
1319 gpr_log(GPR_DEBUG, "... retrying in %" PRId64 ".%09d seconds.",
1320 timeout.tv_sec, timeout.tv_nsec);
1321 } else {
1322 gpr_log(GPR_DEBUG, "... retrying immediately.");
1323 }
1324 }
1325 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
1326 grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
1327 lb_call_on_retry_timer, glb_policy, now);
1328 }
1329 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001330 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1331 "lb_on_server_status_received");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001332}
1333
David Garcia Quintas8d489112016-07-29 15:20:42 -07001334/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001335static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
1336 glb_destroy, glb_shutdown, glb_pick,
1337 glb_cancel_pick, glb_cancel_picks, glb_ping_one,
1338 glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
1339
1340static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
1341
1342static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
1343
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001344static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1345 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1346
1347static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1348
1349grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
1350 return &glb_lb_policy_factory;
1351}
1352
1353/* Plugin registration */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001354void grpc_lb_policy_grpclb_init() {
1355 grpc_register_lb_policy(grpc_glb_lb_factory_create());
1356 grpc_register_tracer("glb", &grpc_lb_glb_trace);
1357}
1358
1359void grpc_lb_policy_grpclb_shutdown() {}