blob: a64414877f071ab4fc148a5ad05717c9e9dff4cf [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
46 * idle state, \a query_for_backends() is called. It creates an instance of \a
David Garcia Quintas43339842016-07-18 12:56:09 -070047 * lb_client_data, an internal struct meant to contain the data associated with
48 * the internal communication with the LB server. This instance is created via
49 * \a lb_client_data_create(). There, the call over lb_channel to pick-first
50 * from {a1..an} is created, the \a LoadBalancingRequest message is assembled
51 * and all necessary callbacks for the progress of the internal call configured.
52 *
53 * Back in \a query_for_backends(), the internal *streaming* call to the LB
54 * server (whichever address from {a1..an} pick-first chose) is kicked off.
55 * It'll progress over the callbacks configured in \a lb_client_data_create()
56 * (see the field docstrings of \a lb_client_data for more details).
57 *
58 * If the call fails with UNIMPLEMENTED, the original call will also fail.
59 * There's a misconfiguration somewhere: at least one of {a1..an} isn't a LB
60 * server, which contradicts the LB bit being set. If the internal call times
61 * out, the usual behavior of pick-first applies, continuing to pick from the
62 * list {a1..an}.
63 *
David Garcia Quintas65318262016-07-29 13:43:38 -070064 * Upon sucesss, a \a LoadBalancingResponse is expected in \a res_recv_cb. An
David Garcia Quintas43339842016-07-18 12:56:09 -070065 * invalid one results in the termination of the streaming call. A new streaming
66 * call should be created if possible, failing the original call otherwise.
67 * For a valid \a LoadBalancingResponse, the server list of actual backends is
68 * extracted. A Round Robin policy will be created from this list. There are two
69 * possible scenarios:
70 *
71 * 1. This is the first server list received. There was no previous instance of
72 * the Round Robin policy. \a rr_handover() will instantiate the RR policy
73 * and perform all the pending operations over it.
74 * 2. There's already a RR policy instance active. We need to introduce the new
75 * one build from the new serverlist, but taking care not to disrupt the
76 * operations in progress over the old RR instance. This is done by
77 * decreasing the reference count on the old policy. The moment no more
78 * references are held on the old RR policy, it'll be destroyed and \a
David Garcia Quintas348cfdb2016-08-19 12:19:43 -070079 * glb_rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN
80 * state. At this point we can transition to a new RR instance safely, which
81 * is done once again via \a rr_handover().
David Garcia Quintas43339842016-07-18 12:56:09 -070082 *
83 *
84 * Once a RR policy instance is in place (and getting updated as described),
85 * calls to for a pick, a ping or a cancellation will be serviced right away by
86 * forwarding them to the RR instance. Any time there's no RR policy available
David Garcia Quintasd4a756b2016-07-19 11:35:15 -070087 * (ie, right after the creation of the gRPCLB policy, if an empty serverlist
David Garcia Quintas43339842016-07-18 12:56:09 -070088 * is received, etc), pick/ping requests are added to a list of pending
89 * picks/pings to be flushed and serviced as part of \a rr_handover() the moment
90 * the RR policy instance becomes available.
91 *
92 * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the
93 * high level design and details. */
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070094
95/* TODO(dgq):
96 * - Implement LB service forwarding (point 2c. in the doc's diagram).
97 */
98
David Garcia Quintas8a81aa12016-08-22 15:06:49 -070099#include <errno.h>
100
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -0700101#include <string.h>
102
103#include <grpc/byte_buffer_reader.h>
104#include <grpc/grpc.h>
105#include <grpc/support/alloc.h>
106#include <grpc/support/host_port.h>
107#include <grpc/support/string_util.h>
David Garcia Quintas69099222016-10-03 11:28:37 -0700108#include <grpc/support/time.h>
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -0700109
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700110#include "src/core/ext/client_config/client_channel_factory.h"
Mark D. Rothc5c38782016-09-16 08:51:01 -0700111#include "src/core/ext/client_config/lb_policy_factory.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700112#include "src/core/ext/client_config/lb_policy_registry.h"
113#include "src/core/ext/client_config/parse_address.h"
David Garcia Quintas8782d1b2016-06-15 23:58:44 -0700114#include "src/core/ext/lb_policy/grpclb/grpclb.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700115#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
David Garcia Quintasbc334912016-08-22 16:57:20 -0700116#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700117#include "src/core/lib/iomgr/sockaddr_utils.h"
118#include "src/core/lib/support/string.h"
119#include "src/core/lib/surface/call.h"
120#include "src/core/lib/surface/channel.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700121#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700122
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700123int grpc_lb_glb_trace = 0;
124
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700125/* add lb_token of selected subchannel (address) to the call's initial
126 * metadata */
127static void initial_metadata_add_lb_token(
128 grpc_metadata_batch *initial_metadata,
129 grpc_linked_mdelem *lb_token_mdelem_storage, grpc_mdelem *lb_token) {
130 GPR_ASSERT(lb_token_mdelem_storage != NULL);
131 GPR_ASSERT(lb_token != NULL);
132 grpc_metadata_batch_add_tail(initial_metadata, lb_token_mdelem_storage,
133 lb_token);
134}
135
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700136typedef struct wrapped_rr_closure_arg {
David Garcia Quintas43339842016-07-18 12:56:09 -0700137 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
138 * calls against the internal RR instance, respectively. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700139 grpc_closure *wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700140
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700141 /* the pick's initial metadata, kept in order to append the LB token for the
142 * pick */
143 grpc_metadata_batch *initial_metadata;
144
145 /* the picked target, used to determine which LB token to add to the pick's
146 * initial metadata */
147 grpc_connected_subchannel **target;
148
149 /* the LB token associated with the pick */
150 grpc_mdelem *lb_token;
151
152 /* storage for the lb token initial metadata mdelem */
153 grpc_linked_mdelem *lb_token_mdelem_storage;
154
David Garcia Quintas43339842016-07-18 12:56:09 -0700155 /* The RR instance related to the closure */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700156 grpc_lb_policy *rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700157
158 /* when not NULL, represents a pending_{pick,ping} node to be freed upon
159 * closure execution */
160 void *owning_pending_node; /* to be freed if not NULL */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700161} wrapped_rr_closure_arg;
162
163/* The \a on_complete closure passed as part of the pick requires keeping a
164 * reference to its associated round robin instance. We wrap this closure in
165 * order to unref the round robin instance upon its invocation */
166static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700167 grpc_error *error) {
David Garcia Quintas43339842016-07-18 12:56:09 -0700168 wrapped_rr_closure_arg *wc_arg = arg;
David Garcia Quintas43339842016-07-18 12:56:09 -0700169 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700170 if (grpc_lb_glb_trace) {
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700171 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
David Garcia Quintas43339842016-07-18 12:56:09 -0700172 (intptr_t)wc_arg->rr_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700173 }
David Garcia Quintas43339842016-07-18 12:56:09 -0700174 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700175
176 /* if target is NULL, no pick has been made by the RR policy (eg, all
177 * addresses failed to connect). There won't be any user_data/token
178 * available */
179 if (wc_arg->target != NULL) {
180 initial_metadata_add_lb_token(wc_arg->initial_metadata,
181 wc_arg->lb_token_mdelem_storage,
182 GRPC_MDELEM_REF(wc_arg->lb_token));
183 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700184 }
David Garcia Quintas5a876162016-07-18 13:08:42 -0700185 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700186
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700187 grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error),
188 NULL);
David Garcia Quintas43339842016-07-18 12:56:09 -0700189 gpr_free(wc_arg->owning_pending_node);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700190}
191
David Garcia Quintasea11d162016-07-14 17:27:28 -0700192/* Linked list of pending pick requests. It stores all information needed to
193 * eventually call (Round Robin's) pick() on them. They mainly stay pending
194 * waiting for the RR policy to be created/updated.
195 *
196 * One particularity is the wrapping of the user-provided \a on_complete closure
197 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
198 * order to correctly unref the RR policy instance upon completion of the pick.
199 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700200typedef struct pending_pick {
201 struct pending_pick *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700202
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700203 /* original pick()'s arguments */
204 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700205
206 /* output argument where to store the pick()ed connected subchannel, or NULL
207 * upon error. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700208 grpc_connected_subchannel **target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700209
210 /* a closure wrapping the original on_complete one to be invoked once the
211 * pick() has completed (regardless of success) */
212 grpc_closure wrapped_on_complete;
213
214 /* args for wrapped_on_complete */
215 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700216} pending_pick;
217
David Garcia Quintas8aace512016-08-15 14:55:12 -0700218static void add_pending_pick(pending_pick **root,
219 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas65318262016-07-29 13:43:38 -0700220 grpc_connected_subchannel **target,
221 grpc_closure *on_complete) {
222 pending_pick *pp = gpr_malloc(sizeof(*pp));
223 memset(pp, 0, sizeof(pending_pick));
224 memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
225 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700226 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700227 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700228 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700229 pp->wrapped_on_complete_arg.target = target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700230 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
231 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
232 pick_args->lb_token_mdelem_storage;
David Garcia Quintas65318262016-07-29 13:43:38 -0700233 grpc_closure_init(&pp->wrapped_on_complete, wrapped_rr_closure,
234 &pp->wrapped_on_complete_arg);
235 *root = pp;
236}
237
David Garcia Quintasea11d162016-07-14 17:27:28 -0700238/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700239typedef struct pending_ping {
240 struct pending_ping *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700241
242 /* a closure wrapping the original on_complete one to be invoked once the
243 * ping() has completed (regardless of success) */
244 grpc_closure wrapped_notify;
245
246 /* args for wrapped_notify */
247 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700248} pending_ping;
249
David Garcia Quintas65318262016-07-29 13:43:38 -0700250static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
251 pending_ping *pping = gpr_malloc(sizeof(*pping));
252 memset(pping, 0, sizeof(pending_ping));
253 memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
254 pping->next = *root;
255 grpc_closure_init(&pping->wrapped_notify, wrapped_rr_closure,
256 &pping->wrapped_notify_arg);
257 pping->wrapped_notify_arg.wrapped_closure = notify;
258 *root = pping;
259}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700260
David Garcia Quintas8d489112016-07-29 15:20:42 -0700261/*
262 * glb_lb_policy
263 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700264typedef struct rr_connectivity_data rr_connectivity_data;
David Garcia Quintasa0e278e2016-08-01 11:36:14 -0700265struct lb_client_data;
David Garcia Quintas65318262016-07-29 13:43:38 -0700266static const grpc_lb_policy_vtable glb_lb_policy_vtable;
267typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700268 /** base policy: must be first */
269 grpc_lb_policy base;
270
271 /** mutex protecting remaining members */
272 gpr_mu mu;
273
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700274 /** who the client is trying to communicate with */
Mark D. Rothd1604af2016-09-22 11:20:27 -0700275 const char *server_name;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700276 grpc_client_channel_factory *cc_factory;
277
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700278 /** deadline for the LB's call */
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700279 gpr_timespec deadline;
280
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700281 /** for communicating with the LB server */
David Garcia Quintasea11d162016-07-14 17:27:28 -0700282 grpc_channel *lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700283
284 /** the RR policy to use of the backend servers returned by the LB server */
285 grpc_lb_policy *rr_policy;
286
287 bool started_picking;
288
289 /** our connectivity state tracker */
290 grpc_connectivity_state_tracker state_tracker;
291
David Garcia Quintasea11d162016-07-14 17:27:28 -0700292 /** stores the deserialized response from the LB. May be NULL until one such
293 * response has arrived. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700294 grpc_grpclb_serverlist *serverlist;
295
Mark D. Roth2b626462016-09-16 09:53:25 -0700296 /** addresses from \a serverlist */
297 grpc_lb_addresses *addresses;
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700298
David Garcia Quintasea11d162016-07-14 17:27:28 -0700299 /** list of picks that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700300 pending_pick *pending_picks;
301
David Garcia Quintasea11d162016-07-14 17:27:28 -0700302 /** list of pings that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700303 pending_ping *pending_pings;
304
David Garcia Quintasea11d162016-07-14 17:27:28 -0700305 /** client data associated with the LB server communication */
David Garcia Quintasa0e278e2016-08-01 11:36:14 -0700306 struct lb_client_data *lb_client;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700307
308 /** for tracking of the RR connectivity */
309 rr_connectivity_data *rr_connectivity;
David Garcia Quintas43339842016-07-18 12:56:09 -0700310
David Garcia Quintas41bef452016-07-28 19:19:58 -0700311 /* a wrapped (see \a wrapped_rr_closure) on-complete closure for readily
312 * available RR picks */
David Garcia Quintas43339842016-07-18 12:56:09 -0700313 grpc_closure wrapped_on_complete;
314
315 /* arguments for the wrapped_on_complete closure */
316 wrapped_rr_closure_arg wc_arg;
David Garcia Quintas65318262016-07-29 13:43:38 -0700317} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700318
David Garcia Quintas65318262016-07-29 13:43:38 -0700319/* Keeps track and reacts to changes in connectivity of the RR instance */
320struct rr_connectivity_data {
321 grpc_closure on_change;
322 grpc_connectivity_state state;
323 glb_lb_policy *glb_policy;
324};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700325
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700326static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
327 bool log) {
328 const grpc_grpclb_ip_address *ip = &server->ip_address;
329 if (server->port >> 16 != 0) {
330 if (log) {
331 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200332 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
333 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700334 }
335 return false;
336 }
337
338 if (ip->size != 4 && ip->size != 16) {
339 if (log) {
340 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200341 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700342 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200343 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700344 }
345 return false;
346 }
347 return true;
348}
349
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700350/* Returns addresses extracted from \a serverlist. */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700351static grpc_lb_addresses *process_serverlist(
Mark D. Rothc5c38782016-09-16 08:51:01 -0700352 const grpc_grpclb_serverlist *serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700353 size_t num_valid = 0;
354 /* first pass: count how many are valid in order to allocate the necessary
355 * memory in a single block */
356 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700357 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700358 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700359 if (num_valid == 0) return NULL;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700360
Mark D. Rothc5c38782016-09-16 08:51:01 -0700361 grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700362
363 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700364 * to the outside world) to be read by the RR policy during its creation.
365 * Given that the validity tests are very cheap, they are performed again
366 * instead of marking the valid ones during the first pass, as this would
367 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700368 size_t addr_idx = 0;
369 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
370 GPR_ASSERT(addr_idx < num_valid);
371 const grpc_grpclb_server *server = serverlist->servers[sl_idx];
372 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700373
374 /* address processing */
375 const uint16_t netorder_port = htons((uint16_t)server->port);
376 /* the addresses are given in binary format (a in(6)_addr struct) in
377 * server->ip_address.bytes. */
378 const grpc_grpclb_ip_address *ip = &server->ip_address;
Mark D. Rothc5c38782016-09-16 08:51:01 -0700379 grpc_resolved_address addr;
380 memset(&addr, 0, sizeof(addr));
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700381 if (ip->size == 4) {
Mark D. Rothc5c38782016-09-16 08:51:01 -0700382 addr.len = sizeof(struct sockaddr_in);
383 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700384 addr4->sin_family = AF_INET;
385 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
386 addr4->sin_port = netorder_port;
387 } else if (ip->size == 16) {
Mark D. Rothc5c38782016-09-16 08:51:01 -0700388 addr.len = sizeof(struct sockaddr_in6);
389 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700390 addr6->sin6_family = AF_INET;
391 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
392 addr6->sin6_port = netorder_port;
393 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700394
395 /* lb token processing */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700396 void *user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700397 if (server->has_load_balance_token) {
398 const size_t lb_token_size =
399 GPR_ARRAY_SIZE(server->load_balance_token) - 1;
400 grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
401 (uint8_t *)server->load_balance_token, lb_token_size);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700402 user_data = grpc_mdelem_from_metadata_strings(
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700403 GRPC_MDSTR_LOAD_REPORTING_INITIAL, lb_token_mdstr);
404 } else {
405 gpr_log(GPR_ERROR,
406 "Missing LB token for backend address '%s'. The empty token will "
407 "be used instead",
Mark D. Rothc5c38782016-09-16 08:51:01 -0700408 grpc_sockaddr_to_uri((struct sockaddr *)&addr.addr));
409 user_data = GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700410 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700411
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700412 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
413 false /* is_balancer */,
Mark D. Rothc5c38782016-09-16 08:51:01 -0700414 NULL /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700415 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700416 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700417 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700418
419 return lb_addresses;
420}
421
Mark D. Roth2b626462016-09-16 09:53:25 -0700422/* A plugin for grpc_lb_addresses_destroy that unrefs the LB token metadata. */
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700423static void lb_token_destroy(void *token) {
Mark D. Rothc5c38782016-09-16 08:51:01 -0700424 if (token != NULL) GRPC_MDELEM_UNREF(token);
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700425}
426
David Garcia Quintas65318262016-07-29 13:43:38 -0700427static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx,
428 const grpc_grpclb_serverlist *serverlist,
429 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700430 GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700431
432 grpc_lb_policy_args args;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700433 memset(&args, 0, sizeof(args));
Mark D. Roth8b7678c2016-09-16 10:51:15 -0700434 args.server_name = glb_policy->server_name;
David Garcia Quintas65318262016-07-29 13:43:38 -0700435 args.client_channel_factory = glb_policy->cc_factory;
Mark D. Rothc5c38782016-09-16 08:51:01 -0700436 args.addresses = process_serverlist(serverlist);
David Garcia Quintas65318262016-07-29 13:43:38 -0700437
438 grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
439
Mark D. Roth2b626462016-09-16 09:53:25 -0700440 if (glb_policy->addresses != NULL) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700441 /* dispose of the previous version */
Mark D. Roth2b626462016-09-16 09:53:25 -0700442 grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700443 }
Mark D. Roth2b626462016-09-16 09:53:25 -0700444 glb_policy->addresses = args.addresses;
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700445
David Garcia Quintas65318262016-07-29 13:43:38 -0700446 return rr;
447}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700448
David Garcia Quintas41bef452016-07-28 19:19:58 -0700449static void rr_handover(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
David Garcia Quintas65318262016-07-29 13:43:38 -0700450 grpc_error *error) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700451 GPR_ASSERT(glb_policy->serverlist != NULL &&
452 glb_policy->serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700453 glb_policy->rr_policy =
454 create_rr(exec_ctx, glb_policy->serverlist, glb_policy);
455
456 if (grpc_lb_glb_trace) {
457 gpr_log(GPR_INFO, "Created RR policy (0x%" PRIxPTR ")",
458 (intptr_t)glb_policy->rr_policy);
459 }
460 GPR_ASSERT(glb_policy->rr_policy != NULL);
461 glb_policy->rr_connectivity->state = grpc_lb_policy_check_connectivity(
462 exec_ctx, glb_policy->rr_policy, &error);
463 grpc_lb_policy_notify_on_state_change(
464 exec_ctx, glb_policy->rr_policy, &glb_policy->rr_connectivity->state,
465 &glb_policy->rr_connectivity->on_change);
466 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700467 glb_policy->rr_connectivity->state,
468 GRPC_ERROR_REF(error), "rr_handover");
David Garcia Quintas65318262016-07-29 13:43:38 -0700469 grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
470
471 /* flush pending ops */
472 pending_pick *pp;
473 while ((pp = glb_policy->pending_picks)) {
474 glb_policy->pending_picks = pp->next;
475 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
476 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
477 if (grpc_lb_glb_trace) {
478 gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
479 (intptr_t)glb_policy->rr_policy);
480 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700481 grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, &pp->pick_args,
482 pp->target,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700483 (void **)&pp->wrapped_on_complete_arg.lb_token,
David Garcia Quintas8aace512016-08-15 14:55:12 -0700484 &pp->wrapped_on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -0700485 pp->wrapped_on_complete_arg.owning_pending_node = pp;
486 }
487
488 pending_ping *pping;
489 while ((pping = glb_policy->pending_pings)) {
490 glb_policy->pending_pings = pping->next;
491 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
492 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
493 if (grpc_lb_glb_trace) {
494 gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
495 (intptr_t)glb_policy->rr_policy);
496 }
497 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
498 &pping->wrapped_notify);
499 pping->wrapped_notify_arg.owning_pending_node = pping;
500 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700501}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700502
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700503static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
504 grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -0700505 rr_connectivity_data *rr_conn_data = arg;
506 glb_lb_policy *glb_policy = rr_conn_data->glb_policy;
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700507
David Garcia Quintas41bef452016-07-28 19:19:58 -0700508 if (rr_conn_data->state == GRPC_CHANNEL_SHUTDOWN) {
509 if (glb_policy->serverlist != NULL) {
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700510 /* a RR policy is shutting down but there's a serverlist available ->
511 * perform a handover */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700512 rr_handover(exec_ctx, glb_policy, error);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700513 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -0700514 /* shutting down and no new serverlist available. Bail out. */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700515 gpr_free(rr_conn_data);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700516 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700517 } else {
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700518 if (error == GRPC_ERROR_NONE) {
David Garcia Quintasea11d162016-07-14 17:27:28 -0700519 /* RR not shutting down. Mimic the RR's policy state */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700520 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700521 rr_conn_data->state, GRPC_ERROR_REF(error),
522 "glb_rr_connectivity_changed");
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700523 /* resubscribe */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700524 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
525 &rr_conn_data->state,
526 &rr_conn_data->on_change);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700527 } else { /* error */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700528 gpr_free(rr_conn_data);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700529 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700530 }
531}
532
David Garcia Quintas65318262016-07-29 13:43:38 -0700533static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
534 grpc_lb_policy_factory *factory,
535 grpc_lb_policy_args *args) {
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700536 /* Count the number of gRPC-LB addresses. There must be at least one.
537 * TODO(roth): For now, we ignore non-balancer addresses, but in the
538 * future, we may change the behavior such that we fall back to using
539 * the non-balancer addresses if we cannot reach any balancers. At that
540 * time, this should be changed to allow a list with no balancer addresses,
541 * since the resolver might fail to return a balancer address even when
542 * this is the right LB policy to use. */
Mark D. Rothf655c852016-09-06 10:40:38 -0700543 size_t num_grpclb_addrs = 0;
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700544 for (size_t i = 0; i < args->addresses->num_addresses; ++i) {
545 if (args->addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
Mark D. Rothf655c852016-09-06 10:40:38 -0700546 }
547 if (num_grpclb_addrs == 0) return NULL;
548
David Garcia Quintas65318262016-07-29 13:43:38 -0700549 glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
550 memset(glb_policy, 0, sizeof(*glb_policy));
551
552 /* All input addresses in args->addresses come from a resolver that claims
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700553 * they are LB services. It's the resolver's responsibility to make sure
554 * this
David Garcia Quintas65318262016-07-29 13:43:38 -0700555 * policy is only instantiated and used in that case.
556 *
557 * Create a client channel over them to communicate with a LB service */
Mark D. Rothd1604af2016-09-22 11:20:27 -0700558 glb_policy->server_name = gpr_strdup(args->server_name);
David Garcia Quintas65318262016-07-29 13:43:38 -0700559 glb_policy->cc_factory = args->client_channel_factory;
560 GPR_ASSERT(glb_policy->cc_factory != NULL);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700561
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700562 /* construct a target from the addresses in args, given in the form
David Garcia Quintas65318262016-07-29 13:43:38 -0700563 * ipvX://ip1:port1,ip2:port2,...
564 * TODO(dgq): support mixed ip version */
Mark D. Rothf655c852016-09-06 10:40:38 -0700565 char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700566 size_t addr_index = 0;
567 for (size_t i = 0; i < args->addresses->num_addresses; i++) {
568 if (args->addresses->addresses[i].user_data != NULL) {
David Garcia Quintas5ebb7af2016-09-15 10:02:16 -0700569 gpr_log(GPR_ERROR,
570 "This LB policy doesn't support user data. It will be ignored");
571 }
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700572 if (args->addresses->addresses[i].is_balancer) {
Mark D. Rothc5c38782016-09-16 08:51:01 -0700573 if (addr_index == 0) {
574 addr_strs[addr_index++] = grpc_sockaddr_to_uri(
575 (const struct sockaddr *)&args->addresses->addresses[i]
576 .address.addr);
577 } else {
578 GPR_ASSERT(grpc_sockaddr_to_string(
579 &addr_strs[addr_index++],
580 (const struct sockaddr *)&args->addresses->addresses[i]
581 .address.addr,
David Garcia Quintas9f852722016-09-30 14:47:15 -0700582 true) > 0);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700583 }
Mark D. Rothf655c852016-09-06 10:40:38 -0700584 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700585 }
586 size_t uri_path_len;
Mark D. Roth989cdcd2016-09-06 13:28:28 -0700587 char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
588 num_grpclb_addrs, ",", &uri_path_len);
David Garcia Quintas65318262016-07-29 13:43:38 -0700589
590 /* will pick using pick_first */
591 glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
592 exec_ctx, glb_policy->cc_factory, target_uri_str,
593 GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL);
594
595 gpr_free(target_uri_str);
Mark D. Rothf655c852016-09-06 10:40:38 -0700596 for (size_t i = 0; i < num_grpclb_addrs; i++) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700597 gpr_free(addr_strs[i]);
598 }
599 gpr_free(addr_strs);
600
601 if (glb_policy->lb_channel == NULL) {
602 gpr_free(glb_policy);
603 return NULL;
604 }
605
606 rr_connectivity_data *rr_connectivity =
607 gpr_malloc(sizeof(rr_connectivity_data));
608 memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700609 grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
David Garcia Quintas65318262016-07-29 13:43:38 -0700610 rr_connectivity);
611 rr_connectivity->glb_policy = glb_policy;
612 glb_policy->rr_connectivity = rr_connectivity;
613
614 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable);
615 gpr_mu_init(&glb_policy->mu);
616 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
617 "grpclb");
618 return &glb_policy->base;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700619}
620
David Garcia Quintas65318262016-07-29 13:43:38 -0700621static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
622 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
623 GPR_ASSERT(glb_policy->pending_picks == NULL);
624 GPR_ASSERT(glb_policy->pending_pings == NULL);
Mark D. Rothd1604af2016-09-22 11:20:27 -0700625 gpr_free((void *)glb_policy->server_name);
David Garcia Quintas65318262016-07-29 13:43:38 -0700626 grpc_channel_destroy(glb_policy->lb_channel);
627 glb_policy->lb_channel = NULL;
628 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
629 if (glb_policy->serverlist != NULL) {
630 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
631 }
632 gpr_mu_destroy(&glb_policy->mu);
Mark D. Roth2b626462016-09-16 09:53:25 -0700633 grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700634 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700635}
636
David Garcia Quintas740759e2016-08-01 14:49:49 -0700637static void lb_client_data_destroy(struct lb_client_data *lb_client);
David Garcia Quintas65318262016-07-29 13:43:38 -0700638static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
639 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
640 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700641
David Garcia Quintas65318262016-07-29 13:43:38 -0700642 pending_pick *pp = glb_policy->pending_picks;
643 glb_policy->pending_picks = NULL;
644 pending_ping *pping = glb_policy->pending_pings;
645 glb_policy->pending_pings = NULL;
646 gpr_mu_unlock(&glb_policy->mu);
647
648 while (pp != NULL) {
649 pending_pick *next = pp->next;
650 *pp->target = NULL;
651 grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, GRPC_ERROR_NONE,
652 NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700653 pp = next;
654 }
655
656 while (pping != NULL) {
657 pending_ping *next = pping->next;
658 grpc_exec_ctx_sched(exec_ctx, &pping->wrapped_notify, GRPC_ERROR_NONE,
659 NULL);
660 pping = next;
661 }
662
663 if (glb_policy->rr_policy) {
664 /* unsubscribe */
665 grpc_lb_policy_notify_on_state_change(
666 exec_ctx, glb_policy->rr_policy, NULL,
667 &glb_policy->rr_connectivity->on_change);
668 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
669 }
670
David Garcia Quintas740759e2016-08-01 14:49:49 -0700671 lb_client_data_destroy(glb_policy->lb_client);
672 glb_policy->lb_client = NULL;
673
David Garcia Quintas65318262016-07-29 13:43:38 -0700674 grpc_connectivity_state_set(
675 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
676 GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown");
677}
678
679static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
Mark D. Roth5f844002016-09-08 08:20:53 -0700680 grpc_connected_subchannel **target,
681 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700682 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
683 gpr_mu_lock(&glb_policy->mu);
684 pending_pick *pp = glb_policy->pending_picks;
685 glb_policy->pending_picks = NULL;
686 while (pp != NULL) {
687 pending_pick *next = pp->next;
688 if (pp->target == target) {
689 grpc_polling_entity_del_from_pollset_set(
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700690 exec_ctx, pp->pick_args.pollent, glb_policy->base.interested_parties);
David Garcia Quintas65318262016-07-29 13:43:38 -0700691 *target = NULL;
Mark D. Roth932b10c2016-09-09 08:44:30 -0700692 grpc_exec_ctx_sched(
693 exec_ctx, &pp->wrapped_on_complete,
694 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700695 } else {
696 pp->next = glb_policy->pending_picks;
697 glb_policy->pending_picks = pp;
698 }
699 pp = next;
700 }
701 gpr_mu_unlock(&glb_policy->mu);
Mark D. Roth5f844002016-09-08 08:20:53 -0700702 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700703}
704
David Garcia Quintasa0e278e2016-08-01 11:36:14 -0700705static grpc_call *lb_client_data_get_call(struct lb_client_data *lb_client);
David Garcia Quintas65318262016-07-29 13:43:38 -0700706static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
707 uint32_t initial_metadata_flags_mask,
Mark D. Rothe65ff112016-09-09 13:48:38 -0700708 uint32_t initial_metadata_flags_eq,
709 grpc_error *error) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700710 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
711 gpr_mu_lock(&glb_policy->mu);
712 if (glb_policy->lb_client != NULL) {
713 /* cancel the call to the load balancer service, if any */
714 grpc_call_cancel(lb_client_data_get_call(glb_policy->lb_client), NULL);
715 }
716 pending_pick *pp = glb_policy->pending_picks;
717 glb_policy->pending_picks = NULL;
718 while (pp != NULL) {
719 pending_pick *next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700720 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -0700721 initial_metadata_flags_eq) {
722 grpc_polling_entity_del_from_pollset_set(
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700723 exec_ctx, pp->pick_args.pollent, glb_policy->base.interested_parties);
Mark D. Roth58f52b72016-09-09 13:55:18 -0700724 grpc_exec_ctx_sched(
725 exec_ctx, &pp->wrapped_on_complete,
726 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700727 } else {
728 pp->next = glb_policy->pending_picks;
729 glb_policy->pending_picks = pp;
730 }
731 pp = next;
732 }
733 gpr_mu_unlock(&glb_policy->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700734 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700735}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700736
David Garcia Quintas65318262016-07-29 13:43:38 -0700737static void query_for_backends(grpc_exec_ctx *exec_ctx,
738 glb_lb_policy *glb_policy);
739static void start_picking(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) {
740 glb_policy->started_picking = true;
741 query_for_backends(exec_ctx, glb_policy);
742}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700743
David Garcia Quintas65318262016-07-29 13:43:38 -0700744static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
745 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
746 gpr_mu_lock(&glb_policy->mu);
747 if (!glb_policy->started_picking) {
748 start_picking(exec_ctx, glb_policy);
749 }
750 gpr_mu_unlock(&glb_policy->mu);
751}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700752
David Garcia Quintas65318262016-07-29 13:43:38 -0700753static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
David Garcia Quintas8aace512016-08-15 14:55:12 -0700754 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700755 grpc_connected_subchannel **target, void **user_data,
David Garcia Quintas65318262016-07-29 13:43:38 -0700756 grpc_closure *on_complete) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700757 if (pick_args->lb_token_mdelem_storage == NULL) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700758 *target = NULL;
David Garcia Quintas6cc44fc2016-09-12 23:04:35 -0700759 grpc_exec_ctx_sched(
760 exec_ctx, on_complete,
761 GRPC_ERROR_CREATE("No mdelem storage for the LB token. Load reporting "
762 "won't work without it. Failing"),
763 NULL);
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700764 return 1;
765 }
766
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700767 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -0700768 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas5cf3c372016-10-03 14:30:03 -0700769 glb_policy->deadline = pick_args->deadline;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700770 bool pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -0700771
772 if (glb_policy->rr_policy != NULL) {
773 if (grpc_lb_glb_trace) {
774 gpr_log(GPR_INFO, "about to PICK from 0x%" PRIxPTR "",
775 (intptr_t)glb_policy->rr_policy);
776 }
777 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
778 memset(&glb_policy->wc_arg, 0, sizeof(wrapped_rr_closure_arg));
779 glb_policy->wc_arg.rr_policy = glb_policy->rr_policy;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700780 glb_policy->wc_arg.target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700781 glb_policy->wc_arg.wrapped_closure = on_complete;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700782 glb_policy->wc_arg.lb_token_mdelem_storage =
783 pick_args->lb_token_mdelem_storage;
784 glb_policy->wc_arg.initial_metadata = pick_args->initial_metadata;
785 glb_policy->wc_arg.owning_pending_node = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -0700786 grpc_closure_init(&glb_policy->wrapped_on_complete, wrapped_rr_closure,
787 &glb_policy->wc_arg);
David Garcia Quintas8aace512016-08-15 14:55:12 -0700788
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700789 pick_done =
790 grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pick_args, target,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700791 (void **)&glb_policy->wc_arg.lb_token,
David Garcia Quintas65318262016-07-29 13:43:38 -0700792 &glb_policy->wrapped_on_complete);
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700793 if (pick_done) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700794 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
David Garcia Quintas65318262016-07-29 13:43:38 -0700795 if (grpc_lb_glb_trace) {
796 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
797 (intptr_t)glb_policy->wc_arg.rr_policy);
798 }
799 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->wc_arg.rr_policy, "glb_pick");
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700800
801 /* add the load reporting initial metadata */
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700802 initial_metadata_add_lb_token(
803 pick_args->initial_metadata, pick_args->lb_token_mdelem_storage,
David Garcia Quintas8424fdc2016-09-15 08:35:59 -0700804 GRPC_MDELEM_REF(glb_policy->wc_arg.lb_token));
David Garcia Quintas65318262016-07-29 13:43:38 -0700805 }
David Garcia Quintas69099222016-10-03 11:28:37 -0700806 } else {
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700807 /* else, the pending pick will be registered and taken care of by the
808 * pending pick list inside the RR policy (glb_policy->rr_policy) */
David Garcia Quintas8aace512016-08-15 14:55:12 -0700809 grpc_polling_entity_add_to_pollset_set(exec_ctx, pick_args->pollent,
David Garcia Quintas65318262016-07-29 13:43:38 -0700810 glb_policy->base.interested_parties);
David Garcia Quintas8aace512016-08-15 14:55:12 -0700811 add_pending_pick(&glb_policy->pending_picks, pick_args, target,
812 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -0700813
814 if (!glb_policy->started_picking) {
815 start_picking(exec_ctx, glb_policy);
816 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700817 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -0700818 }
819 gpr_mu_unlock(&glb_policy->mu);
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700820 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -0700821}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700822
David Garcia Quintas65318262016-07-29 13:43:38 -0700823static grpc_connectivity_state glb_check_connectivity(
824 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
825 grpc_error **connectivity_error) {
826 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
827 grpc_connectivity_state st;
828 gpr_mu_lock(&glb_policy->mu);
829 st = grpc_connectivity_state_check(&glb_policy->state_tracker,
830 connectivity_error);
831 gpr_mu_unlock(&glb_policy->mu);
832 return st;
833}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700834
David Garcia Quintas65318262016-07-29 13:43:38 -0700835static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
836 grpc_closure *closure) {
837 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
838 gpr_mu_lock(&glb_policy->mu);
839 if (glb_policy->rr_policy) {
840 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
841 } else {
842 add_pending_ping(&glb_policy->pending_pings, closure);
843 if (!glb_policy->started_picking) {
844 start_picking(exec_ctx, glb_policy);
845 }
846 }
847 gpr_mu_unlock(&glb_policy->mu);
848}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700849
David Garcia Quintas65318262016-07-29 13:43:38 -0700850static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
851 grpc_lb_policy *pol,
852 grpc_connectivity_state *current,
853 grpc_closure *notify) {
854 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
855 gpr_mu_lock(&glb_policy->mu);
856 grpc_connectivity_state_notify_on_state_change(
857 exec_ctx, &glb_policy->state_tracker, current, notify);
858
859 gpr_mu_unlock(&glb_policy->mu);
860}
861
David Garcia Quintas8d489112016-07-29 15:20:42 -0700862/*
863 * lb_client_data
864 *
865 * Used internally for the client call to the LB */
David Garcia Quintas65318262016-07-29 13:43:38 -0700866typedef struct lb_client_data {
867 gpr_mu mu;
868
869 /* called once initial metadata's been sent */
870 grpc_closure md_sent;
871
David Garcia Quintas65318262016-07-29 13:43:38 -0700872 /* called once the LoadBalanceRequest has been sent to the LB server. See
873 * src/proto/grpc/.../load_balancer.proto */
874 grpc_closure req_sent;
875
876 /* A response from the LB server has been received (or error). Process it */
877 grpc_closure res_rcvd;
878
879 /* After the client has sent a close to the LB server */
880 grpc_closure close_sent;
881
882 /* ... and the status from the LB server has been received */
883 grpc_closure srv_status_rcvd;
884
885 grpc_call *lb_call; /* streaming call to the LB server, */
886 gpr_timespec deadline; /* for the streaming call to the LB server */
887
888 grpc_metadata_array initial_metadata_recv; /* initial MD from LB server */
889 grpc_metadata_array trailing_metadata_recv; /* trailing MD from LB server */
890
891 /* what's being sent to the LB server. Note that its value may vary if the LB
892 * server indicates a redirect. */
893 grpc_byte_buffer *request_payload;
894
895 /* response from the LB server, if any. Processed in res_recv_cb() */
896 grpc_byte_buffer *response_payload;
897
898 /* the call's status and status detailset in srv_status_rcvd_cb() */
899 grpc_status_code status;
900 char *status_details;
901 size_t status_details_capacity;
902
903 /* pointer back to the enclosing policy */
904 glb_lb_policy *glb_policy;
905} lb_client_data;
906
907static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700908static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700909static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
910static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg,
911 grpc_error *error);
912static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg,
913 grpc_error *error);
914
915static lb_client_data *lb_client_data_create(glb_lb_policy *glb_policy) {
David Garcia Quintas55ba14a2016-09-27 18:45:30 -0700916 GPR_ASSERT(glb_policy->server_name != NULL);
917 GPR_ASSERT(glb_policy->server_name[0] != '\0');
918
David Garcia Quintas65318262016-07-29 13:43:38 -0700919 lb_client_data *lb_client = gpr_malloc(sizeof(lb_client_data));
920 memset(lb_client, 0, sizeof(lb_client_data));
921
922 gpr_mu_init(&lb_client->mu);
923 grpc_closure_init(&lb_client->md_sent, md_sent_cb, lb_client);
924
David Garcia Quintas65318262016-07-29 13:43:38 -0700925 grpc_closure_init(&lb_client->req_sent, req_sent_cb, lb_client);
926 grpc_closure_init(&lb_client->res_rcvd, res_recv_cb, lb_client);
927 grpc_closure_init(&lb_client->close_sent, close_sent_cb, lb_client);
928 grpc_closure_init(&lb_client->srv_status_rcvd, srv_status_rcvd_cb, lb_client);
929
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700930 lb_client->deadline = glb_policy->deadline;
David Garcia Quintas65318262016-07-29 13:43:38 -0700931
David Garcia Quintas15eba132016-08-09 15:20:48 -0700932 /* Note the following LB call progresses every time there's activity in \a
933 * glb_policy->base.interested_parties, which is comprised of the polling
934 * entities passed to glb_pick(). */
David Garcia Quintas65318262016-07-29 13:43:38 -0700935 lb_client->lb_call = grpc_channel_create_pollset_set_call(
936 glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -0700937 glb_policy->base.interested_parties,
David Garcia Quintas55ba14a2016-09-27 18:45:30 -0700938 "/grpc.lb.v1.LoadBalancer/BalanceLoad", glb_policy->server_name,
939 lb_client->deadline, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700940
941 grpc_metadata_array_init(&lb_client->initial_metadata_recv);
942 grpc_metadata_array_init(&lb_client->trailing_metadata_recv);
943
David Garcia Quintas55ba14a2016-09-27 18:45:30 -0700944 grpc_grpclb_request *request =
945 grpc_grpclb_request_create(glb_policy->server_name);
David Garcia Quintas65318262016-07-29 13:43:38 -0700946 gpr_slice request_payload_slice = grpc_grpclb_request_encode(request);
947 lb_client->request_payload =
948 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
949 gpr_slice_unref(request_payload_slice);
950 grpc_grpclb_request_destroy(request);
951
952 lb_client->status_details = NULL;
953 lb_client->status_details_capacity = 0;
954 lb_client->glb_policy = glb_policy;
955 return lb_client;
956}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700957
David Garcia Quintas65318262016-07-29 13:43:38 -0700958static void lb_client_data_destroy(lb_client_data *lb_client) {
David Garcia Quintas740759e2016-08-01 14:49:49 -0700959 grpc_call_destroy(lb_client->lb_call);
David Garcia Quintas65318262016-07-29 13:43:38 -0700960 grpc_metadata_array_destroy(&lb_client->initial_metadata_recv);
961 grpc_metadata_array_destroy(&lb_client->trailing_metadata_recv);
962
963 grpc_byte_buffer_destroy(lb_client->request_payload);
964
965 gpr_free(lb_client->status_details);
966 gpr_mu_destroy(&lb_client->mu);
967 gpr_free(lb_client);
968}
969static grpc_call *lb_client_data_get_call(lb_client_data *lb_client) {
970 return lb_client->lb_call;
971}
972
David Garcia Quintas8d489112016-07-29 15:20:42 -0700973/*
974 * Auxiliary functions and LB client callbacks.
975 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700976static void query_for_backends(grpc_exec_ctx *exec_ctx,
977 glb_lb_policy *glb_policy) {
978 GPR_ASSERT(glb_policy->lb_channel != NULL);
979
980 glb_policy->lb_client = lb_client_data_create(glb_policy);
981 grpc_call_error call_error;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700982 grpc_op ops[1];
983 memset(ops, 0, sizeof(ops));
984 grpc_op *op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -0700985 op->op = GRPC_OP_SEND_INITIAL_METADATA;
986 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700987 op->flags = 0;
988 op->reserved = NULL;
989 op++;
David Garcia Quintas65318262016-07-29 13:43:38 -0700990 call_error = grpc_call_start_batch_and_execute(
991 exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops),
992 &glb_policy->lb_client->md_sent);
993 GPR_ASSERT(GRPC_CALL_OK == call_error);
994
995 op = ops;
996 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
997 op->data.recv_status_on_client.trailing_metadata =
998 &glb_policy->lb_client->trailing_metadata_recv;
999 op->data.recv_status_on_client.status = &glb_policy->lb_client->status;
1000 op->data.recv_status_on_client.status_details =
1001 &glb_policy->lb_client->status_details;
1002 op->data.recv_status_on_client.status_details_capacity =
1003 &glb_policy->lb_client->status_details_capacity;
1004 op->flags = 0;
1005 op->reserved = NULL;
1006 op++;
1007 call_error = grpc_call_start_batch_and_execute(
1008 exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops),
1009 &glb_policy->lb_client->srv_status_rcvd);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001010 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001011}
1012
David Garcia Quintas4166cb02016-07-29 14:33:15 -07001013static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
1014 lb_client_data *lb_client = arg;
1015 GPR_ASSERT(lb_client->lb_call);
1016 grpc_op ops[1];
1017 memset(ops, 0, sizeof(ops));
1018 grpc_op *op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001019
1020 op->op = GRPC_OP_SEND_MESSAGE;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001021 op->data.send_message = lb_client->request_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001022 op->flags = 0;
1023 op->reserved = NULL;
1024 op++;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001025 grpc_call_error call_error = grpc_call_start_batch_and_execute(
1026 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1027 &lb_client->req_sent);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001028 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001029}
1030
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001031static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001032 lb_client_data *lb_client = arg;
David Garcia Quintas601bb122016-08-18 15:03:59 -07001033 GPR_ASSERT(lb_client->lb_call);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001034
David Garcia Quintas601bb122016-08-18 15:03:59 -07001035 grpc_op ops[2];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001036 memset(ops, 0, sizeof(ops));
1037 grpc_op *op = ops;
1038
David Garcia Quintas601bb122016-08-18 15:03:59 -07001039 op->op = GRPC_OP_RECV_INITIAL_METADATA;
1040 op->data.recv_initial_metadata = &lb_client->initial_metadata_recv;
1041 op->flags = 0;
1042 op->reserved = NULL;
1043 op++;
1044
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001045 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001046 op->data.recv_message = &lb_client->response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001047 op->flags = 0;
1048 op->reserved = NULL;
1049 op++;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001050 grpc_call_error call_error = grpc_call_start_batch_and_execute(
1051 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1052 &lb_client->res_rcvd);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001053 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001054}
1055
David Garcia Quintas65318262016-07-29 13:43:38 -07001056static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001057 lb_client_data *lb_client = arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001058 grpc_op ops[2];
1059 memset(ops, 0, sizeof(ops));
1060 grpc_op *op = ops;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001061 if (lb_client->response_payload != NULL) {
1062 /* Received data from the LB server. Look inside
David Garcia Quintas601bb122016-08-18 15:03:59 -07001063 * lb_client->response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001064 grpc_byte_buffer_reader bbr;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001065 grpc_byte_buffer_reader_init(&bbr, lb_client->response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001066 gpr_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001067 grpc_byte_buffer_destroy(lb_client->response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001068 grpc_grpclb_serverlist *serverlist =
1069 grpc_grpclb_response_parse_serverlist(response_slice);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001070 if (serverlist != NULL) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001071 gpr_slice_unref(response_slice);
1072 if (grpc_lb_glb_trace) {
Jan Tattermusch2b398082016-10-07 14:40:30 +02001073 gpr_log(GPR_INFO, "Serverlist with %lu servers received",
1074 (unsigned long)serverlist->num_servers);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001075 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001076
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001077 /* update serverlist */
1078 if (serverlist->num_servers > 0) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001079 if (grpc_grpclb_serverlist_equals(lb_client->glb_policy->serverlist,
1080 serverlist)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001081 if (grpc_lb_glb_trace) {
1082 gpr_log(GPR_INFO,
1083 "Incoming server list identical to current, ignoring.");
1084 }
1085 } else { /* new serverlist */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001086 if (lb_client->glb_policy->serverlist != NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001087 /* dispose of the old serverlist */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001088 grpc_grpclb_destroy_serverlist(lb_client->glb_policy->serverlist);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001089 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001090 /* and update the copy in the glb_lb_policy instance */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001091 lb_client->glb_policy->serverlist = serverlist;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001092 }
David Garcia Quintas41bef452016-07-28 19:19:58 -07001093 if (lb_client->glb_policy->rr_policy == NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001094 /* initial "handover", in this case from a null RR policy, meaning
David Garcia Quintas43339842016-07-18 12:56:09 -07001095 * it'll just create the first RR policy instance */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001096 rr_handover(exec_ctx, lb_client->glb_policy, error);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001097 } else {
1098 /* unref the RR policy, eventually leading to its substitution with a
1099 * new one constructed from the received serverlist (see
David Garcia Quintas348cfdb2016-08-19 12:19:43 -07001100 * glb_rr_connectivity_changed) */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001101 GRPC_LB_POLICY_UNREF(exec_ctx, lb_client->glb_policy->rr_policy,
David Garcia Quintasea11d162016-07-14 17:27:28 -07001102 "serverlist_received");
1103 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001104 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001105 if (grpc_lb_glb_trace) {
1106 gpr_log(GPR_INFO,
1107 "Received empty server list. Picks will stay pending until a "
1108 "response with > 0 servers is received");
1109 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001110 }
1111
David Garcia Quintasea11d162016-07-14 17:27:28 -07001112 /* keep listening for serverlist updates */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001113 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001114 op->data.recv_message = &lb_client->response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001115 op->flags = 0;
1116 op->reserved = NULL;
1117 op++;
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001118 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas41bef452016-07-28 19:19:58 -07001119 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1120 &lb_client->res_rcvd); /* loop */
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001121 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001122 return;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001123 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001124
1125 GPR_ASSERT(serverlist == NULL);
1126 gpr_log(GPR_ERROR, "Invalid LB response received: '%s'",
1127 gpr_dump_slice(response_slice, GPR_DUMP_ASCII));
1128 gpr_slice_unref(response_slice);
1129
1130 /* Disconnect from server returning invalid response. */
1131 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
1132 op->flags = 0;
1133 op->reserved = NULL;
1134 op++;
1135 grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas41bef452016-07-28 19:19:58 -07001136 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1137 &lb_client->close_sent);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001138 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001139 }
1140 /* empty payload: call cancelled by server. Cleanups happening in
1141 * srv_status_rcvd_cb */
1142}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001143
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001144static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg,
1145 grpc_error *error) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001146 if (grpc_lb_glb_trace) {
1147 gpr_log(GPR_INFO,
1148 "Close from LB client sent. Waiting from server status now");
1149 }
1150}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001151
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001152static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001153 grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001154 lb_client_data *lb_client = arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001155 if (grpc_lb_glb_trace) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001156 gpr_log(GPR_INFO,
1157 "status from lb server received. Status = %d, Details = '%s', "
Jan Tattermusch2b398082016-10-07 14:40:30 +02001158 "Capacity "
1159 "= %lu",
David Garcia Quintas41bef452016-07-28 19:19:58 -07001160 lb_client->status, lb_client->status_details,
Jan Tattermusch2b398082016-10-07 14:40:30 +02001161 (unsigned long)lb_client->status_details_capacity);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001162 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -07001163 /* TODO(dgq): deal with stream termination properly (fire up another one?
David Garcia Quintas8424fdc2016-09-15 08:35:59 -07001164 * fail the original call?) */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001165}
1166
David Garcia Quintas8d489112016-07-29 15:20:42 -07001167/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001168static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
1169 glb_destroy, glb_shutdown, glb_pick,
1170 glb_cancel_pick, glb_cancel_picks, glb_ping_one,
1171 glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
1172
1173static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
1174
1175static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
1176
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001177static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1178 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1179
1180static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1181
1182grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
1183 return &glb_lb_policy_factory;
1184}
1185
1186/* Plugin registration */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001187void grpc_lb_policy_grpclb_init() {
1188 grpc_register_lb_policy(grpc_glb_lb_factory_create());
1189 grpc_register_tracer("glb", &grpc_lb_glb_trace);
1190}
1191
1192void grpc_lb_policy_grpclb_shutdown() {}