blob: 9a176ba0d106487dcaeeaaa3090df8bc2c3b7fbc [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>
108
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700109#include "src/core/ext/client_config/client_channel_factory.h"
110#include "src/core/ext/client_config/lb_policy_registry.h"
111#include "src/core/ext/client_config/parse_address.h"
David Garcia Quintas8782d1b2016-06-15 23:58:44 -0700112#include "src/core/ext/lb_policy/grpclb/grpclb.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700113#include "src/core/ext/lb_policy/grpclb/load_balancer_api.h"
David Garcia Quintasbc334912016-08-22 16:57:20 -0700114#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700115#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700116#include "src/core/lib/support/string.h"
117#include "src/core/lib/surface/call.h"
118#include "src/core/lib/surface/channel.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700119#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700120
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700121int grpc_lb_glb_trace = 0;
122
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700123static void *user_data_copy(void *user_data) {
124 if (user_data == NULL) return NULL;
125 return GRPC_MDELEM_REF(user_data);
126}
127
128static void user_data_destroy(void *user_data) {
129 if (user_data == NULL) return;
130 GRPC_MDELEM_UNREF(user_data);
131}
132
133/* 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 Quintas43339842016-07-18 12:56:09 -0700145 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
146 * calls against the internal RR instance, respectively. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700147 grpc_closure *wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700148
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700149 /* the pick's initial metadata, kept in order to append the LB token for the
150 * pick */
151 grpc_metadata_batch *initial_metadata;
152
153 /* the picked target, used to determine which LB token to add to the pick's
154 * initial metadata */
155 grpc_connected_subchannel **target;
156
157 /* the LB token associated with the pick */
158 grpc_mdelem *lb_token;
159
160 /* storage for the lb token initial metadata mdelem */
161 grpc_linked_mdelem *lb_token_mdelem_storage;
162
David Garcia Quintas43339842016-07-18 12:56:09 -0700163 /* The RR instance related to the closure */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700164 grpc_lb_policy *rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700165
166 /* when not NULL, represents a pending_{pick,ping} node to be freed upon
167 * closure execution */
168 void *owning_pending_node; /* to be freed if not NULL */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700169} wrapped_rr_closure_arg;
170
171/* The \a on_complete closure passed as part of the pick requires keeping a
172 * reference to its associated round robin instance. We wrap this closure in
173 * order to unref the round robin instance upon its invocation */
174static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700175 grpc_error *error) {
David Garcia Quintas43339842016-07-18 12:56:09 -0700176 wrapped_rr_closure_arg *wc_arg = arg;
David Garcia Quintas43339842016-07-18 12:56:09 -0700177 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700178 if (grpc_lb_glb_trace) {
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700179 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
David Garcia Quintas43339842016-07-18 12:56:09 -0700180 (intptr_t)wc_arg->rr_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700181 }
David Garcia Quintas43339842016-07-18 12:56:09 -0700182 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700183 }
David Garcia Quintas5a876162016-07-18 13:08:42 -0700184 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700185
186 initial_metadata_add_lb_token(wc_arg->initial_metadata,
187 wc_arg->lb_token_mdelem_storage,
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700188 user_data_copy(wc_arg->lb_token));
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700189
David Garcia Quintas5a876162016-07-18 13:08:42 -0700190 grpc_exec_ctx_sched(exec_ctx, wc_arg->wrapped_closure, error, NULL);
David Garcia Quintas43339842016-07-18 12:56:09 -0700191 gpr_free(wc_arg->owning_pending_node);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700192}
193
David Garcia Quintasea11d162016-07-14 17:27:28 -0700194/* Linked list of pending pick requests. It stores all information needed to
195 * eventually call (Round Robin's) pick() on them. They mainly stay pending
196 * waiting for the RR policy to be created/updated.
197 *
198 * One particularity is the wrapping of the user-provided \a on_complete closure
199 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
200 * order to correctly unref the RR policy instance upon completion of the pick.
201 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700202typedef struct pending_pick {
203 struct pending_pick *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700204
205 /* polling entity for the pick()'s async notification */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700206 grpc_polling_entity *pollent;
David Garcia Quintas43339842016-07-18 12:56:09 -0700207
208 /* the initial metadata for the pick. See grpc_lb_policy_pick() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700209 grpc_metadata_batch *initial_metadata;
David Garcia Quintas43339842016-07-18 12:56:09 -0700210
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700211 /* storage for the lb token initial metadata mdelem */
212 grpc_linked_mdelem *lb_token_mdelem_storage;
213
David Garcia Quintas43339842016-07-18 12:56:09 -0700214 /* bitmask passed to pick() and used for selective cancelling. See
215 * grpc_lb_policy_cancel_picks() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700216 uint32_t initial_metadata_flags;
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
222 /* a closure wrapping the original on_complete one to be invoked once the
223 * pick() has completed (regardless of success) */
224 grpc_closure wrapped_on_complete;
225
226 /* args for wrapped_on_complete */
227 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700228} pending_pick;
229
David Garcia Quintas8aace512016-08-15 14:55:12 -0700230static void add_pending_pick(pending_pick **root,
231 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas65318262016-07-29 13:43:38 -0700232 grpc_connected_subchannel **target,
233 grpc_closure *on_complete) {
234 pending_pick *pp = gpr_malloc(sizeof(*pp));
235 memset(pp, 0, sizeof(pending_pick));
236 memset(&pp->wrapped_on_complete_arg, 0, sizeof(wrapped_rr_closure_arg));
237 pp->next = *root;
David Garcia Quintas8aace512016-08-15 14:55:12 -0700238 pp->pollent = pick_args->pollent;
David Garcia Quintas65318262016-07-29 13:43:38 -0700239 pp->target = target;
David Garcia Quintas8aace512016-08-15 14:55:12 -0700240 pp->initial_metadata = pick_args->initial_metadata;
241 pp->initial_metadata_flags = pick_args->initial_metadata_flags;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700242 pp->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
David Garcia Quintas65318262016-07-29 13:43:38 -0700243 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700244 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
245 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
246 pick_args->lb_token_mdelem_storage;
David Garcia Quintas65318262016-07-29 13:43:38 -0700247 grpc_closure_init(&pp->wrapped_on_complete, wrapped_rr_closure,
248 &pp->wrapped_on_complete_arg);
249 *root = pp;
250}
251
David Garcia Quintasea11d162016-07-14 17:27:28 -0700252/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700253typedef struct pending_ping {
254 struct pending_ping *next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700255
256 /* a closure wrapping the original on_complete one to be invoked once the
257 * ping() has completed (regardless of success) */
258 grpc_closure wrapped_notify;
259
260 /* args for wrapped_notify */
261 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700262} pending_ping;
263
David Garcia Quintas65318262016-07-29 13:43:38 -0700264static void add_pending_ping(pending_ping **root, grpc_closure *notify) {
265 pending_ping *pping = gpr_malloc(sizeof(*pping));
266 memset(pping, 0, sizeof(pending_ping));
267 memset(&pping->wrapped_notify_arg, 0, sizeof(wrapped_rr_closure_arg));
268 pping->next = *root;
269 grpc_closure_init(&pping->wrapped_notify, wrapped_rr_closure,
270 &pping->wrapped_notify_arg);
271 pping->wrapped_notify_arg.wrapped_closure = notify;
272 *root = pping;
273}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700274
David Garcia Quintas8d489112016-07-29 15:20:42 -0700275/*
276 * glb_lb_policy
277 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700278typedef struct rr_connectivity_data rr_connectivity_data;
David Garcia Quintasa0e278e2016-08-01 11:36:14 -0700279struct lb_client_data;
David Garcia Quintas65318262016-07-29 13:43:38 -0700280static const grpc_lb_policy_vtable glb_lb_policy_vtable;
281typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700282 /** base policy: must be first */
283 grpc_lb_policy base;
284
285 /** mutex protecting remaining members */
286 gpr_mu mu;
287
288 grpc_client_channel_factory *cc_factory;
289
290 /** for communicating with the LB server */
David Garcia Quintasea11d162016-07-14 17:27:28 -0700291 grpc_channel *lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700292
293 /** the RR policy to use of the backend servers returned by the LB server */
294 grpc_lb_policy *rr_policy;
295
296 bool started_picking;
297
298 /** our connectivity state tracker */
299 grpc_connectivity_state_tracker state_tracker;
300
David Garcia Quintasea11d162016-07-14 17:27:28 -0700301 /** stores the deserialized response from the LB. May be NULL until one such
302 * response has arrived. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700303 grpc_grpclb_serverlist *serverlist;
304
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700305 /** total number of valid addresses received in \a serverlist */
306 size_t num_ok_serverlist_addresses;
307
308 /** LB addresses from \a serverlist, \a num_ok_serverlist_addresses of them */
309 grpc_lb_address *lb_addresses;
310
David Garcia Quintasea11d162016-07-14 17:27:28 -0700311 /** list of picks that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700312 pending_pick *pending_picks;
313
David Garcia Quintasea11d162016-07-14 17:27:28 -0700314 /** list of pings that are waiting on RR's policy connectivity */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700315 pending_ping *pending_pings;
316
David Garcia Quintasea11d162016-07-14 17:27:28 -0700317 /** client data associated with the LB server communication */
David Garcia Quintasa0e278e2016-08-01 11:36:14 -0700318 struct lb_client_data *lb_client;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700319
320 /** for tracking of the RR connectivity */
321 rr_connectivity_data *rr_connectivity;
David Garcia Quintas43339842016-07-18 12:56:09 -0700322
David Garcia Quintas41bef452016-07-28 19:19:58 -0700323 /* a wrapped (see \a wrapped_rr_closure) on-complete closure for readily
324 * available RR picks */
David Garcia Quintas43339842016-07-18 12:56:09 -0700325 grpc_closure wrapped_on_complete;
326
327 /* arguments for the wrapped_on_complete closure */
328 wrapped_rr_closure_arg wc_arg;
David Garcia Quintas65318262016-07-29 13:43:38 -0700329} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700330
David Garcia Quintas65318262016-07-29 13:43:38 -0700331/* Keeps track and reacts to changes in connectivity of the RR instance */
332struct rr_connectivity_data {
333 grpc_closure on_change;
334 grpc_connectivity_state state;
335 glb_lb_policy *glb_policy;
336};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700337
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700338static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
339 bool log) {
340 const grpc_grpclb_ip_address *ip = &server->ip_address;
341 if (server->port >> 16 != 0) {
342 if (log) {
343 gpr_log(GPR_ERROR,
344 "Invalid port '%d' at index %zu of serverlist. Ignoring.",
345 server->port, idx);
346 }
347 return false;
348 }
349
350 if (ip->size != 4 && ip->size != 16) {
351 if (log) {
352 gpr_log(GPR_ERROR,
353 "Expected IP to be 4 or 16 bytes, got %d at index %zu of "
354 "serverlist. Ignoring",
355 ip->size, idx);
356 }
357 return false;
358 }
359 return true;
360}
361
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700362/* populate \a addresses according to \a serverlist. Returns the number of
363 * addresses successfully parsed and added to \a addresses */
364static size_t process_serverlist(const grpc_grpclb_serverlist *serverlist,
365 grpc_lb_address **lb_addresses) {
366 size_t num_valid = 0;
367 /* first pass: count how many are valid in order to allocate the necessary
368 * memory in a single block */
369 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700370 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700371 }
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700372 if (num_valid == 0) {
373 return 0;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700374 }
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700375
376 /* allocate the memory block for the "resolved" addresses. */
377 grpc_resolved_address *r_addrs_memblock =
378 gpr_malloc(sizeof(grpc_resolved_address) * num_valid);
379 memset(r_addrs_memblock, 0, sizeof(grpc_resolved_address) * num_valid);
380 grpc_lb_address *lb_addrs = gpr_malloc(sizeof(grpc_lb_address) * num_valid);
381 memset(lb_addrs, 0, sizeof(grpc_lb_address) * num_valid);
382
383 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700384 * to the outside world) to be read by the RR policy during its creation.
385 * Given that the validity tests are very cheap, they are performed again
386 * instead of marking the valid ones during the first pass, as this would
387 * incurr in an allocation due to the arbitrary number of server */
388 size_t num_processed = 0;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700389 for (size_t i = 0; i < num_valid; ++i) {
390 const grpc_grpclb_server *server = serverlist->servers[i];
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700391 if (!is_server_valid(serverlist->servers[i], i, false)) continue;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700392 grpc_lb_address *const lb_addr = &lb_addrs[i];
393
394 /* lb token processing */
395 if (server->has_load_balance_token) {
396 const size_t lb_token_size =
397 GPR_ARRAY_SIZE(server->load_balance_token) - 1;
398 grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
399 (uint8_t *)server->load_balance_token, lb_token_size);
400 lb_addr->user_data = grpc_mdelem_from_metadata_strings(
401 GRPC_MDSTR_LOAD_REPORTING_INITIAL, lb_token_mdstr);
402 }
403
404 /* address processing */
405 const uint16_t netorder_port = htons((uint16_t)server->port);
406 /* the addresses are given in binary format (a in(6)_addr struct) in
407 * server->ip_address.bytes. */
408 const grpc_grpclb_ip_address *ip = &server->ip_address;
409
410 lb_addr->resolved_address = &r_addrs_memblock[i];
411 struct sockaddr_storage *sa =
412 (struct sockaddr_storage *)lb_addr->resolved_address->addr;
413 size_t *sa_len = &lb_addr->resolved_address->len;
414 *sa_len = 0;
415 if (ip->size == 4) {
416 struct sockaddr_in *addr4 = (struct sockaddr_in *)sa;
417 *sa_len = sizeof(struct sockaddr_in);
418 memset(addr4, 0, *sa_len);
419 addr4->sin_family = AF_INET;
420 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
421 addr4->sin_port = netorder_port;
422 } else if (ip->size == 16) {
423 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)sa;
424 *sa_len = sizeof(struct sockaddr_in6);
425 memset(addr6, 0, *sa_len);
426 addr6->sin6_family = AF_INET;
427 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
428 addr6->sin6_port = netorder_port;
429 }
430 GPR_ASSERT(*sa_len > 0);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700431 ++num_processed;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700432 }
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700433 GPR_ASSERT(num_processed == num_valid);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700434 *lb_addresses = lb_addrs;
435 return num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700436}
437
David Garcia Quintas65318262016-07-29 13:43:38 -0700438static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx,
439 const grpc_grpclb_serverlist *serverlist,
440 glb_lb_policy *glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700441 GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700442
443 grpc_lb_policy_args args;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700444 memset(&args, 0, sizeof(args));
David Garcia Quintas65318262016-07-29 13:43:38 -0700445 args.client_channel_factory = glb_policy->cc_factory;
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700446 const size_t num_ok_addresses =
447 process_serverlist(serverlist, &args.lb_addresses);
448 args.num_addresses = num_ok_addresses;
David Garcia Quintas65318262016-07-29 13:43:38 -0700449
450 grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700451
452 glb_policy->num_ok_serverlist_addresses = num_ok_addresses;
453 if (glb_policy->lb_addresses != NULL) {
454 /* dispose of the previous version */
455 for (size_t i = 0; i < num_ok_addresses; ++i) {
456 user_data_destroy(glb_policy->lb_addresses[i].user_data);
457 }
458 gpr_free(glb_policy->lb_addresses);
459 }
460
461 glb_policy->lb_addresses = args.lb_addresses;
462
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700463 if (args.num_addresses > 0) {
464 /* free "resolved" addresses memblock */
465 gpr_free(args.lb_addresses->resolved_address);
466 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700467 return rr;
468}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700469
David Garcia Quintas41bef452016-07-28 19:19:58 -0700470static void rr_handover(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
David Garcia Quintas65318262016-07-29 13:43:38 -0700471 grpc_error *error) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700472 GPR_ASSERT(glb_policy->serverlist != NULL &&
473 glb_policy->serverlist->num_servers > 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700474 glb_policy->rr_policy =
475 create_rr(exec_ctx, glb_policy->serverlist, glb_policy);
476
477 if (grpc_lb_glb_trace) {
478 gpr_log(GPR_INFO, "Created RR policy (0x%" PRIxPTR ")",
479 (intptr_t)glb_policy->rr_policy);
480 }
481 GPR_ASSERT(glb_policy->rr_policy != NULL);
482 glb_policy->rr_connectivity->state = grpc_lb_policy_check_connectivity(
483 exec_ctx, glb_policy->rr_policy, &error);
484 grpc_lb_policy_notify_on_state_change(
485 exec_ctx, glb_policy->rr_policy, &glb_policy->rr_connectivity->state,
486 &glb_policy->rr_connectivity->on_change);
487 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700488 glb_policy->rr_connectivity->state,
489 GRPC_ERROR_REF(error), "rr_handover");
David Garcia Quintas65318262016-07-29 13:43:38 -0700490 grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
491
492 /* flush pending ops */
493 pending_pick *pp;
494 while ((pp = glb_policy->pending_picks)) {
495 glb_policy->pending_picks = pp->next;
496 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
497 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
498 if (grpc_lb_glb_trace) {
499 gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "",
500 (intptr_t)glb_policy->rr_policy);
501 }
David Garcia Quintas8aace512016-08-15 14:55:12 -0700502 const grpc_lb_policy_pick_args pick_args = {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700503 pp->pollent, pp->initial_metadata, pp->initial_metadata_flags,
504 pp->lb_token_mdelem_storage};
David Garcia Quintas8aace512016-08-15 14:55:12 -0700505 grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, &pick_args, pp->target,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700506 (void **)&pp->wrapped_on_complete_arg.lb_token,
David Garcia Quintas8aace512016-08-15 14:55:12 -0700507 &pp->wrapped_on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -0700508 pp->wrapped_on_complete_arg.owning_pending_node = pp;
509 }
510
511 pending_ping *pping;
512 while ((pping = glb_policy->pending_pings)) {
513 glb_policy->pending_pings = pping->next;
514 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
515 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
516 if (grpc_lb_glb_trace) {
517 gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "",
518 (intptr_t)glb_policy->rr_policy);
519 }
520 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy,
521 &pping->wrapped_notify);
522 pping->wrapped_notify_arg.owning_pending_node = pping;
523 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700524}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700525
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700526static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
527 grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -0700528 rr_connectivity_data *rr_conn_data = arg;
529 glb_lb_policy *glb_policy = rr_conn_data->glb_policy;
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700530
David Garcia Quintas41bef452016-07-28 19:19:58 -0700531 if (rr_conn_data->state == GRPC_CHANNEL_SHUTDOWN) {
532 if (glb_policy->serverlist != NULL) {
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700533 /* a RR policy is shutting down but there's a serverlist available ->
534 * perform a handover */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700535 rr_handover(exec_ctx, glb_policy, error);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700536 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -0700537 /* shutting down and no new serverlist available. Bail out. */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700538 gpr_free(rr_conn_data);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700539 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700540 } else {
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700541 if (error == GRPC_ERROR_NONE) {
David Garcia Quintasea11d162016-07-14 17:27:28 -0700542 /* RR not shutting down. Mimic the RR's policy state */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700543 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
David Garcia Quintas348cfdb2016-08-19 12:19:43 -0700544 rr_conn_data->state, GRPC_ERROR_REF(error),
545 "glb_rr_connectivity_changed");
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700546 /* resubscribe */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700547 grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
548 &rr_conn_data->state,
549 &rr_conn_data->on_change);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700550 } else { /* error */
David Garcia Quintas41bef452016-07-28 19:19:58 -0700551 gpr_free(rr_conn_data);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -0700552 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700553 }
554}
555
David Garcia Quintas65318262016-07-29 13:43:38 -0700556static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
557 grpc_lb_policy_factory *factory,
558 grpc_lb_policy_args *args) {
559 glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
560 memset(glb_policy, 0, sizeof(*glb_policy));
561
562 /* All input addresses in args->addresses come from a resolver that claims
563 * they are LB services. It's the resolver's responsibility to make sure this
564 * policy is only instantiated and used in that case.
565 *
566 * Create a client channel over them to communicate with a LB service */
567 glb_policy->cc_factory = args->client_channel_factory;
568 GPR_ASSERT(glb_policy->cc_factory != NULL);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700569 if (args->num_addresses == 0) {
David Garcia Quintas65318262016-07-29 13:43:38 -0700570 return NULL;
571 }
572
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700573 /* construct a target from the addresses in args, given in the form
David Garcia Quintas65318262016-07-29 13:43:38 -0700574 * ipvX://ip1:port1,ip2:port2,...
575 * TODO(dgq): support mixed ip version */
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700576 char **addr_strs = gpr_malloc(sizeof(char *) * args->num_addresses);
577 addr_strs[0] = grpc_sockaddr_to_uri(
578 (const struct sockaddr *)&args->lb_addresses[0].resolved_address->addr);
579 for (size_t i = 1; i < args->num_addresses; i++) {
580 GPR_ASSERT(
581 grpc_sockaddr_to_string(&addr_strs[i],
582 (const struct sockaddr *)&args->lb_addresses[i]
583 .resolved_address->addr,
584 true) == 0);
David Garcia Quintas65318262016-07-29 13:43:38 -0700585 }
586 size_t uri_path_len;
587 char *target_uri_str = gpr_strjoin_sep(
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700588 (const char **)addr_strs, args->num_addresses, ",", &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);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700596 for (size_t i = 0; i < args->num_addresses; 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);
625 grpc_channel_destroy(glb_policy->lb_channel);
626 glb_policy->lb_channel = NULL;
627 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
628 if (glb_policy->serverlist != NULL) {
629 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
630 }
631 gpr_mu_destroy(&glb_policy->mu);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700632
633 for (size_t i = 0; i < glb_policy->num_ok_serverlist_addresses; ++i) {
634 user_data_destroy(glb_policy->lb_addresses[i].user_data);
635 }
636 gpr_free(glb_policy->lb_addresses);
David Garcia Quintas65318262016-07-29 13:43:38 -0700637 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700638}
639
David Garcia Quintas740759e2016-08-01 14:49:49 -0700640static void lb_client_data_destroy(struct lb_client_data *lb_client);
David Garcia Quintas65318262016-07-29 13:43:38 -0700641static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
642 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
643 gpr_mu_lock(&glb_policy->mu);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700644
David Garcia Quintas65318262016-07-29 13:43:38 -0700645 pending_pick *pp = glb_policy->pending_picks;
646 glb_policy->pending_picks = NULL;
647 pending_ping *pping = glb_policy->pending_pings;
648 glb_policy->pending_pings = NULL;
649 gpr_mu_unlock(&glb_policy->mu);
650
651 while (pp != NULL) {
652 pending_pick *next = pp->next;
653 *pp->target = NULL;
654 grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete, GRPC_ERROR_NONE,
655 NULL);
656 gpr_free(pp);
657 pp = next;
658 }
659
660 while (pping != NULL) {
661 pending_ping *next = pping->next;
662 grpc_exec_ctx_sched(exec_ctx, &pping->wrapped_notify, GRPC_ERROR_NONE,
663 NULL);
664 pping = next;
665 }
666
667 if (glb_policy->rr_policy) {
668 /* unsubscribe */
669 grpc_lb_policy_notify_on_state_change(
670 exec_ctx, glb_policy->rr_policy, NULL,
671 &glb_policy->rr_connectivity->on_change);
672 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
673 }
674
David Garcia Quintas740759e2016-08-01 14:49:49 -0700675 lb_client_data_destroy(glb_policy->lb_client);
676 glb_policy->lb_client = NULL;
677
David Garcia Quintas65318262016-07-29 13:43:38 -0700678 grpc_connectivity_state_set(
679 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
680 GRPC_ERROR_CREATE("Channel Shutdown"), "glb_shutdown");
681}
682
683static void glb_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
684 grpc_connected_subchannel **target) {
685 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
686 gpr_mu_lock(&glb_policy->mu);
687 pending_pick *pp = glb_policy->pending_picks;
688 glb_policy->pending_picks = NULL;
689 while (pp != NULL) {
690 pending_pick *next = pp->next;
691 if (pp->target == target) {
692 grpc_polling_entity_del_from_pollset_set(
693 exec_ctx, pp->pollent, glb_policy->base.interested_parties);
694 *target = NULL;
695 grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete,
696 GRPC_ERROR_CANCELLED, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700697 } else {
698 pp->next = glb_policy->pending_picks;
699 glb_policy->pending_picks = pp;
700 }
701 pp = next;
702 }
703 gpr_mu_unlock(&glb_policy->mu);
704}
705
David Garcia Quintasa0e278e2016-08-01 11:36:14 -0700706static grpc_call *lb_client_data_get_call(struct lb_client_data *lb_client);
David Garcia Quintas65318262016-07-29 13:43:38 -0700707static void glb_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
708 uint32_t initial_metadata_flags_mask,
709 uint32_t initial_metadata_flags_eq) {
710 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;
720 if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
721 initial_metadata_flags_eq) {
722 grpc_polling_entity_del_from_pollset_set(
723 exec_ctx, pp->pollent, glb_policy->base.interested_parties);
724 grpc_exec_ctx_sched(exec_ctx, &pp->wrapped_on_complete,
725 GRPC_ERROR_CANCELLED, NULL);
David Garcia Quintas65318262016-07-29 13:43:38 -0700726 } else {
727 pp->next = glb_policy->pending_picks;
728 glb_policy->pending_picks = pp;
729 }
730 pp = next;
731 }
732 gpr_mu_unlock(&glb_policy->mu);
733}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700734
David Garcia Quintas65318262016-07-29 13:43:38 -0700735static void query_for_backends(grpc_exec_ctx *exec_ctx,
736 glb_lb_policy *glb_policy);
737static void start_picking(grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy) {
738 glb_policy->started_picking = true;
739 query_for_backends(exec_ctx, glb_policy);
740}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700741
David Garcia Quintas65318262016-07-29 13:43:38 -0700742static void glb_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
743 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
744 gpr_mu_lock(&glb_policy->mu);
745 if (!glb_policy->started_picking) {
746 start_picking(exec_ctx, glb_policy);
747 }
748 gpr_mu_unlock(&glb_policy->mu);
749}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700750
David Garcia Quintas65318262016-07-29 13:43:38 -0700751static int glb_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
David Garcia Quintas8aace512016-08-15 14:55:12 -0700752 const grpc_lb_policy_pick_args *pick_args,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700753 grpc_connected_subchannel **target, void **user_data,
David Garcia Quintas65318262016-07-29 13:43:38 -0700754 grpc_closure *on_complete) {
755 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -0700756
757 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 Quintas65318262016-07-29 13:43:38 -0700767 gpr_mu_lock(&glb_policy->mu);
768 int r;
769
770 if (glb_policy->rr_policy != NULL) {
771 if (grpc_lb_glb_trace) {
772 gpr_log(GPR_INFO, "about to PICK from 0x%" PRIxPTR "",
773 (intptr_t)glb_policy->rr_policy);
774 }
775 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
776 memset(&glb_policy->wc_arg, 0, sizeof(wrapped_rr_closure_arg));
777 glb_policy->wc_arg.rr_policy = glb_policy->rr_policy;
778 glb_policy->wc_arg.wrapped_closure = on_complete;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700779 glb_policy->wc_arg.lb_token_mdelem_storage =
780 pick_args->lb_token_mdelem_storage;
781 glb_policy->wc_arg.initial_metadata = pick_args->initial_metadata;
782 glb_policy->wc_arg.owning_pending_node = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -0700783 grpc_closure_init(&glb_policy->wrapped_on_complete, wrapped_rr_closure,
784 &glb_policy->wc_arg);
David Garcia Quintas8aace512016-08-15 14:55:12 -0700785
786 r = grpc_lb_policy_pick(exec_ctx, glb_policy->rr_policy, pick_args, target,
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700787 (void **)&glb_policy->wc_arg.lb_token,
David Garcia Quintas65318262016-07-29 13:43:38 -0700788 &glb_policy->wrapped_on_complete);
789 if (r != 0) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700790 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
David Garcia Quintas65318262016-07-29 13:43:38 -0700791 if (grpc_lb_glb_trace) {
792 gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")",
793 (intptr_t)glb_policy->wc_arg.rr_policy);
794 }
795 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->wc_arg.rr_policy, "glb_pick");
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700796
797 /* add the load reporting initial metadata */
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700798 initial_metadata_add_lb_token(
799 pick_args->initial_metadata, pick_args->lb_token_mdelem_storage,
800 user_data_copy(glb_policy->wc_arg.lb_token));
David Garcia Quintas65318262016-07-29 13:43:38 -0700801 }
802 } else {
David Garcia Quintas8aace512016-08-15 14:55:12 -0700803 grpc_polling_entity_add_to_pollset_set(exec_ctx, pick_args->pollent,
David Garcia Quintas65318262016-07-29 13:43:38 -0700804 glb_policy->base.interested_parties);
David Garcia Quintas8aace512016-08-15 14:55:12 -0700805 add_pending_pick(&glb_policy->pending_picks, pick_args, target,
806 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -0700807
808 if (!glb_policy->started_picking) {
809 start_picking(exec_ctx, glb_policy);
810 }
811 r = 0;
812 }
813 gpr_mu_unlock(&glb_policy->mu);
814 return r;
815}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700816
David Garcia Quintas65318262016-07-29 13:43:38 -0700817static grpc_connectivity_state glb_check_connectivity(
818 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
819 grpc_error **connectivity_error) {
820 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
821 grpc_connectivity_state st;
822 gpr_mu_lock(&glb_policy->mu);
823 st = grpc_connectivity_state_check(&glb_policy->state_tracker,
824 connectivity_error);
825 gpr_mu_unlock(&glb_policy->mu);
826 return st;
827}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700828
David Garcia Quintas65318262016-07-29 13:43:38 -0700829static void glb_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
830 grpc_closure *closure) {
831 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
832 gpr_mu_lock(&glb_policy->mu);
833 if (glb_policy->rr_policy) {
834 grpc_lb_policy_ping_one(exec_ctx, glb_policy->rr_policy, closure);
835 } else {
836 add_pending_ping(&glb_policy->pending_pings, closure);
837 if (!glb_policy->started_picking) {
838 start_picking(exec_ctx, glb_policy);
839 }
840 }
841 gpr_mu_unlock(&glb_policy->mu);
842}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700843
David Garcia Quintas65318262016-07-29 13:43:38 -0700844static void glb_notify_on_state_change(grpc_exec_ctx *exec_ctx,
845 grpc_lb_policy *pol,
846 grpc_connectivity_state *current,
847 grpc_closure *notify) {
848 glb_lb_policy *glb_policy = (glb_lb_policy *)pol;
849 gpr_mu_lock(&glb_policy->mu);
850 grpc_connectivity_state_notify_on_state_change(
851 exec_ctx, &glb_policy->state_tracker, current, notify);
852
853 gpr_mu_unlock(&glb_policy->mu);
854}
855
David Garcia Quintas8d489112016-07-29 15:20:42 -0700856/*
857 * lb_client_data
858 *
859 * Used internally for the client call to the LB */
David Garcia Quintas65318262016-07-29 13:43:38 -0700860typedef struct lb_client_data {
861 gpr_mu mu;
862
863 /* called once initial metadata's been sent */
864 grpc_closure md_sent;
865
David Garcia Quintas65318262016-07-29 13:43:38 -0700866 /* called once the LoadBalanceRequest has been sent to the LB server. See
867 * src/proto/grpc/.../load_balancer.proto */
868 grpc_closure req_sent;
869
870 /* A response from the LB server has been received (or error). Process it */
871 grpc_closure res_rcvd;
872
873 /* After the client has sent a close to the LB server */
874 grpc_closure close_sent;
875
876 /* ... and the status from the LB server has been received */
877 grpc_closure srv_status_rcvd;
878
879 grpc_call *lb_call; /* streaming call to the LB server, */
880 gpr_timespec deadline; /* for the streaming call to the LB server */
881
882 grpc_metadata_array initial_metadata_recv; /* initial MD from LB server */
883 grpc_metadata_array trailing_metadata_recv; /* trailing MD from LB server */
884
885 /* what's being sent to the LB server. Note that its value may vary if the LB
886 * server indicates a redirect. */
887 grpc_byte_buffer *request_payload;
888
889 /* response from the LB server, if any. Processed in res_recv_cb() */
890 grpc_byte_buffer *response_payload;
891
892 /* the call's status and status detailset in srv_status_rcvd_cb() */
893 grpc_status_code status;
894 char *status_details;
895 size_t status_details_capacity;
896
897 /* pointer back to the enclosing policy */
898 glb_lb_policy *glb_policy;
899} lb_client_data;
900
901static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700902static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
David Garcia Quintas65318262016-07-29 13:43:38 -0700903static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error);
904static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg,
905 grpc_error *error);
906static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg,
907 grpc_error *error);
908
909static lb_client_data *lb_client_data_create(glb_lb_policy *glb_policy) {
910 lb_client_data *lb_client = gpr_malloc(sizeof(lb_client_data));
911 memset(lb_client, 0, sizeof(lb_client_data));
912
913 gpr_mu_init(&lb_client->mu);
914 grpc_closure_init(&lb_client->md_sent, md_sent_cb, lb_client);
915
David Garcia Quintas65318262016-07-29 13:43:38 -0700916 grpc_closure_init(&lb_client->req_sent, req_sent_cb, lb_client);
917 grpc_closure_init(&lb_client->res_rcvd, res_recv_cb, lb_client);
918 grpc_closure_init(&lb_client->close_sent, close_sent_cb, lb_client);
919 grpc_closure_init(&lb_client->srv_status_rcvd, srv_status_rcvd_cb, lb_client);
920
921 /* TODO(dgq): get the deadline from the client config instead of fabricating
922 * one here. */
923 lb_client->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
924 gpr_time_from_seconds(3, GPR_TIMESPAN));
925
David Garcia Quintas15eba132016-08-09 15:20:48 -0700926 /* Note the following LB call progresses every time there's activity in \a
927 * glb_policy->base.interested_parties, which is comprised of the polling
928 * entities passed to glb_pick(). */
David Garcia Quintas65318262016-07-29 13:43:38 -0700929 lb_client->lb_call = grpc_channel_create_pollset_set_call(
930 glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
931 glb_policy->base.interested_parties, "/BalanceLoad",
932 NULL, /* FIXME(dgq): which "host" value to use? */
933 lb_client->deadline, NULL);
934
935 grpc_metadata_array_init(&lb_client->initial_metadata_recv);
936 grpc_metadata_array_init(&lb_client->trailing_metadata_recv);
937
938 grpc_grpclb_request *request = grpc_grpclb_request_create(
939 "load.balanced.service.name"); /* FIXME(dgq): get the name of the load
940 balanced service from the resolver */
941 gpr_slice request_payload_slice = grpc_grpclb_request_encode(request);
942 lb_client->request_payload =
943 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
944 gpr_slice_unref(request_payload_slice);
945 grpc_grpclb_request_destroy(request);
946
947 lb_client->status_details = NULL;
948 lb_client->status_details_capacity = 0;
949 lb_client->glb_policy = glb_policy;
950 return lb_client;
951}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700952
David Garcia Quintas65318262016-07-29 13:43:38 -0700953static void lb_client_data_destroy(lb_client_data *lb_client) {
David Garcia Quintas740759e2016-08-01 14:49:49 -0700954 grpc_call_destroy(lb_client->lb_call);
David Garcia Quintas65318262016-07-29 13:43:38 -0700955 grpc_metadata_array_destroy(&lb_client->initial_metadata_recv);
956 grpc_metadata_array_destroy(&lb_client->trailing_metadata_recv);
957
958 grpc_byte_buffer_destroy(lb_client->request_payload);
959
960 gpr_free(lb_client->status_details);
961 gpr_mu_destroy(&lb_client->mu);
962 gpr_free(lb_client);
963}
964static grpc_call *lb_client_data_get_call(lb_client_data *lb_client) {
965 return lb_client->lb_call;
966}
967
David Garcia Quintas8d489112016-07-29 15:20:42 -0700968/*
969 * Auxiliary functions and LB client callbacks.
970 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700971static void query_for_backends(grpc_exec_ctx *exec_ctx,
972 glb_lb_policy *glb_policy) {
973 GPR_ASSERT(glb_policy->lb_channel != NULL);
974
975 glb_policy->lb_client = lb_client_data_create(glb_policy);
976 grpc_call_error call_error;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700977 grpc_op ops[1];
978 memset(ops, 0, sizeof(ops));
979 grpc_op *op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -0700980 op->op = GRPC_OP_SEND_INITIAL_METADATA;
981 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700982 op->flags = 0;
983 op->reserved = NULL;
984 op++;
David Garcia Quintas65318262016-07-29 13:43:38 -0700985 call_error = grpc_call_start_batch_and_execute(
986 exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops),
987 &glb_policy->lb_client->md_sent);
988 GPR_ASSERT(GRPC_CALL_OK == call_error);
989
990 op = ops;
991 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
992 op->data.recv_status_on_client.trailing_metadata =
993 &glb_policy->lb_client->trailing_metadata_recv;
994 op->data.recv_status_on_client.status = &glb_policy->lb_client->status;
995 op->data.recv_status_on_client.status_details =
996 &glb_policy->lb_client->status_details;
997 op->data.recv_status_on_client.status_details_capacity =
998 &glb_policy->lb_client->status_details_capacity;
999 op->flags = 0;
1000 op->reserved = NULL;
1001 op++;
1002 call_error = grpc_call_start_batch_and_execute(
1003 exec_ctx, glb_policy->lb_client->lb_call, ops, (size_t)(op - ops),
1004 &glb_policy->lb_client->srv_status_rcvd);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001005 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001006}
1007
David Garcia Quintas4166cb02016-07-29 14:33:15 -07001008static void md_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
1009 lb_client_data *lb_client = arg;
1010 GPR_ASSERT(lb_client->lb_call);
1011 grpc_op ops[1];
1012 memset(ops, 0, sizeof(ops));
1013 grpc_op *op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001014
1015 op->op = GRPC_OP_SEND_MESSAGE;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001016 op->data.send_message = lb_client->request_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001017 op->flags = 0;
1018 op->reserved = NULL;
1019 op++;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001020 grpc_call_error call_error = grpc_call_start_batch_and_execute(
1021 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1022 &lb_client->req_sent);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001023 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001024}
1025
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001026static void req_sent_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001027 lb_client_data *lb_client = arg;
David Garcia Quintas601bb122016-08-18 15:03:59 -07001028 GPR_ASSERT(lb_client->lb_call);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001029
David Garcia Quintas601bb122016-08-18 15:03:59 -07001030 grpc_op ops[2];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001031 memset(ops, 0, sizeof(ops));
1032 grpc_op *op = ops;
1033
David Garcia Quintas601bb122016-08-18 15:03:59 -07001034 op->op = GRPC_OP_RECV_INITIAL_METADATA;
1035 op->data.recv_initial_metadata = &lb_client->initial_metadata_recv;
1036 op->flags = 0;
1037 op->reserved = NULL;
1038 op++;
1039
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001040 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001041 op->data.recv_message = &lb_client->response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001042 op->flags = 0;
1043 op->reserved = NULL;
1044 op++;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001045 grpc_call_error call_error = grpc_call_start_batch_and_execute(
1046 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1047 &lb_client->res_rcvd);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001048 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001049}
1050
David Garcia Quintas65318262016-07-29 13:43:38 -07001051static void res_recv_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001052 lb_client_data *lb_client = arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001053 grpc_op ops[2];
1054 memset(ops, 0, sizeof(ops));
1055 grpc_op *op = ops;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001056 if (lb_client->response_payload != NULL) {
1057 /* Received data from the LB server. Look inside
David Garcia Quintas601bb122016-08-18 15:03:59 -07001058 * lb_client->response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001059 grpc_byte_buffer_reader bbr;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001060 grpc_byte_buffer_reader_init(&bbr, lb_client->response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001061 gpr_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001062 grpc_byte_buffer_destroy(lb_client->response_payload);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001063 grpc_grpclb_serverlist *serverlist =
1064 grpc_grpclb_response_parse_serverlist(response_slice);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001065 if (serverlist != NULL) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001066 gpr_slice_unref(response_slice);
1067 if (grpc_lb_glb_trace) {
1068 gpr_log(GPR_INFO, "Serverlist with %zu servers received",
1069 serverlist->num_servers);
1070 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001071
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001072 /* update serverlist */
1073 if (serverlist->num_servers > 0) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001074 if (grpc_grpclb_serverlist_equals(lb_client->glb_policy->serverlist,
1075 serverlist)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001076 if (grpc_lb_glb_trace) {
1077 gpr_log(GPR_INFO,
1078 "Incoming server list identical to current, ignoring.");
1079 }
1080 } else { /* new serverlist */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001081 if (lb_client->glb_policy->serverlist != NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001082 /* dispose of the old serverlist */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001083 grpc_grpclb_destroy_serverlist(lb_client->glb_policy->serverlist);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001084 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001085 /* and update the copy in the glb_lb_policy instance */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001086 lb_client->glb_policy->serverlist = serverlist;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001087 }
David Garcia Quintas41bef452016-07-28 19:19:58 -07001088 if (lb_client->glb_policy->rr_policy == NULL) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001089 /* initial "handover", in this case from a null RR policy, meaning
David Garcia Quintas43339842016-07-18 12:56:09 -07001090 * it'll just create the first RR policy instance */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001091 rr_handover(exec_ctx, lb_client->glb_policy, error);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001092 } else {
1093 /* unref the RR policy, eventually leading to its substitution with a
1094 * new one constructed from the received serverlist (see
David Garcia Quintas348cfdb2016-08-19 12:19:43 -07001095 * glb_rr_connectivity_changed) */
David Garcia Quintas41bef452016-07-28 19:19:58 -07001096 GRPC_LB_POLICY_UNREF(exec_ctx, lb_client->glb_policy->rr_policy,
David Garcia Quintasea11d162016-07-14 17:27:28 -07001097 "serverlist_received");
1098 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001099 } else {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001100 if (grpc_lb_glb_trace) {
1101 gpr_log(GPR_INFO,
1102 "Received empty server list. Picks will stay pending until a "
1103 "response with > 0 servers is received");
1104 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001105 }
1106
David Garcia Quintasea11d162016-07-14 17:27:28 -07001107 /* keep listening for serverlist updates */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001108 op->op = GRPC_OP_RECV_MESSAGE;
David Garcia Quintas41bef452016-07-28 19:19:58 -07001109 op->data.recv_message = &lb_client->response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001110 op->flags = 0;
1111 op->reserved = NULL;
1112 op++;
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001113 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas41bef452016-07-28 19:19:58 -07001114 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1115 &lb_client->res_rcvd); /* loop */
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001116 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001117 return;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001118 }
David Garcia Quintasea11d162016-07-14 17:27:28 -07001119
1120 GPR_ASSERT(serverlist == NULL);
1121 gpr_log(GPR_ERROR, "Invalid LB response received: '%s'",
1122 gpr_dump_slice(response_slice, GPR_DUMP_ASCII));
1123 gpr_slice_unref(response_slice);
1124
1125 /* Disconnect from server returning invalid response. */
1126 op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
1127 op->flags = 0;
1128 op->reserved = NULL;
1129 op++;
1130 grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas41bef452016-07-28 19:19:58 -07001131 exec_ctx, lb_client->lb_call, ops, (size_t)(op - ops),
1132 &lb_client->close_sent);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001133 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001134 }
1135 /* empty payload: call cancelled by server. Cleanups happening in
1136 * srv_status_rcvd_cb */
1137}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001138
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001139static void close_sent_cb(grpc_exec_ctx *exec_ctx, void *arg,
1140 grpc_error *error) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001141 if (grpc_lb_glb_trace) {
1142 gpr_log(GPR_INFO,
1143 "Close from LB client sent. Waiting from server status now");
1144 }
1145}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001146
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001147static void srv_status_rcvd_cb(grpc_exec_ctx *exec_ctx, void *arg,
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001148 grpc_error *error) {
David Garcia Quintas41bef452016-07-28 19:19:58 -07001149 lb_client_data *lb_client = arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001150 if (grpc_lb_glb_trace) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001151 gpr_log(GPR_INFO,
1152 "status from lb server received. Status = %d, Details = '%s', "
1153 "Capaticy "
1154 "= %zu",
David Garcia Quintas41bef452016-07-28 19:19:58 -07001155 lb_client->status, lb_client->status_details,
1156 lb_client->status_details_capacity);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001157 }
David Garcia Quintas43339842016-07-18 12:56:09 -07001158 /* TODO(dgq): deal with stream termination properly (fire up another one? fail
1159 * the original call?) */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001160}
1161
David Garcia Quintas8d489112016-07-29 15:20:42 -07001162/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001163static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
1164 glb_destroy, glb_shutdown, glb_pick,
1165 glb_cancel_pick, glb_cancel_picks, glb_ping_one,
1166 glb_exit_idle, glb_check_connectivity, glb_notify_on_state_change};
1167
1168static void glb_factory_ref(grpc_lb_policy_factory *factory) {}
1169
1170static void glb_factory_unref(grpc_lb_policy_factory *factory) {}
1171
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001172static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1173 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1174
1175static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1176
1177grpc_lb_policy_factory *grpc_glb_lb_factory_create() {
1178 return &glb_lb_policy_factory;
1179}
1180
1181/* Plugin registration */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001182void grpc_lb_policy_grpclb_init() {
1183 grpc_register_lb_policy(grpc_glb_lb_factory_create());
1184 grpc_register_tracer("glb", &grpc_lb_glb_trace);
1185}
1186
1187void grpc_lb_policy_grpclb_shutdown() {}