blob: 564979c677aee74c3a5ff62e99da375f4f01ffde [file] [log] [blame]
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2016 gRPC authors.
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
David Garcia Quintas3fb8f732016-06-15 22:53:08 -070016 *
17 */
18
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070019/** Implementation of the gRPC LB policy.
20 *
David Garcia Quintas43339842016-07-18 12:56:09 -070021 * This policy takes as input a set of resolved addresses {a1..an} for which the
22 * LB set was set (it's the resolver's responsibility to ensure this). That is
23 * to say, {a1..an} represent a collection of LB servers.
24 *
25 * An internal channel (\a glb_lb_policy.lb_channel) is created over {a1..an}.
26 * This channel behaves just like a regular channel. In particular, the
27 * constructed URI over the addresses a1..an will use the default pick first
28 * policy to select from this list of LB server backends.
29 *
David Garcia Quintas41bef452016-07-28 19:19:58 -070030 * The first time the policy gets a request for a pick, a ping, or to exit the
David Garcia Quintas98da61b2016-10-29 08:46:31 +020031 * idle state, \a query_for_backends_locked() is called. This function sets up
32 * and initiates the internal communication with the LB server. In particular,
33 * it's responsible for instantiating the internal *streaming* call to the LB
34 * server (whichever address from {a1..an} pick-first chose). This call is
David Garcia Quintas7ec29132016-11-01 04:09:05 +010035 * serviced by two callbacks, \a lb_on_server_status_received and \a
36 * lb_on_response_received. The former will be called when the call to the LB
37 * server completes. This can happen if the LB server closes the connection or
38 * if this policy itself cancels the call (for example because it's shutting
David Garcia Quintas246c5642016-11-01 11:16:52 -070039 * down). If the internal call times out, the usual behavior of pick-first
David Garcia Quintas7ec29132016-11-01 04:09:05 +010040 * applies, continuing to pick from the list {a1..an}.
David Garcia Quintas43339842016-07-18 12:56:09 -070041 *
David Garcia Quintas98da61b2016-10-29 08:46:31 +020042 * Upon sucesss, the incoming \a LoadBalancingResponse is processed by \a
43 * res_recv. An invalid one results in the termination of the streaming call. A
44 * new streaming call should be created if possible, failing the original call
45 * otherwise. For a valid \a LoadBalancingResponse, the server list of actual
46 * backends is extracted. A Round Robin policy will be created from this list.
47 * There are two possible scenarios:
David Garcia Quintas43339842016-07-18 12:56:09 -070048 *
49 * 1. This is the first server list received. There was no previous instance of
David Garcia Quintas90712d52016-10-13 19:33:04 -070050 * the Round Robin policy. \a rr_handover_locked() will instantiate the RR
51 * policy and perform all the pending operations over it.
David Garcia Quintas43339842016-07-18 12:56:09 -070052 * 2. There's already a RR policy instance active. We need to introduce the new
53 * one build from the new serverlist, but taking care not to disrupt the
54 * operations in progress over the old RR instance. This is done by
55 * decreasing the reference count on the old policy. The moment no more
56 * references are held on the old RR policy, it'll be destroyed and \a
David Garcia Quintas348cfdb2016-08-19 12:19:43 -070057 * glb_rr_connectivity_changed notified with a \a GRPC_CHANNEL_SHUTDOWN
58 * state. At this point we can transition to a new RR instance safely, which
David Garcia Quintas90712d52016-10-13 19:33:04 -070059 * is done once again via \a rr_handover_locked().
David Garcia Quintas43339842016-07-18 12:56:09 -070060 *
61 *
62 * Once a RR policy instance is in place (and getting updated as described),
63 * calls to for a pick, a ping or a cancellation will be serviced right away by
64 * forwarding them to the RR instance. Any time there's no RR policy available
David Garcia Quintas7ec29132016-11-01 04:09:05 +010065 * (ie, right after the creation of the gRPCLB policy, if an empty serverlist is
66 * received, etc), pick/ping requests are added to a list of pending picks/pings
67 * to be flushed and serviced as part of \a rr_handover_locked() the moment the
68 * RR policy instance becomes available.
David Garcia Quintas43339842016-07-18 12:56:09 -070069 *
70 * \see https://github.com/grpc/grpc/blob/master/doc/load-balancing.md for the
71 * high level design and details. */
David Garcia Quintas8b3b97f2016-07-15 07:46:47 -070072
73/* TODO(dgq):
74 * - Implement LB service forwarding (point 2c. in the doc's diagram).
75 */
76
murgatroid99085f9af2016-10-24 09:55:44 -070077/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when
78 using that endpoint. Because of various transitive includes in uv.h,
79 including windows.h on Windows, uv.h must be included before other system
80 headers. Therefore, sockaddr.h must always be included first */
murgatroid997871f732016-09-23 13:49:05 -070081#include "src/core/lib/iomgr/sockaddr.h"
82
Yash Tibrewalfcd26bc2017-09-25 15:08:28 -070083#include <inttypes.h>
Mark D. Roth64d922a2017-05-03 12:52:04 -070084#include <limits.h>
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -070085#include <string.h>
86
87#include <grpc/byte_buffer_reader.h>
88#include <grpc/grpc.h>
89#include <grpc/support/alloc.h>
90#include <grpc/support/host_port.h>
91#include <grpc/support/string_util.h>
David Garcia Quintas69099222016-10-03 11:28:37 -070092#include <grpc/support/time.h>
David Garcia Quintas22e8f1d2016-06-15 23:53:00 -070093
Craig Tiller9eb0fde2017-03-31 16:59:30 -070094#include "src/core/ext/filters/client_channel/client_channel.h"
95#include "src/core/ext/filters/client_channel/client_channel_factory.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -070096#include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
Craig Tiller9eb0fde2017-03-31 16:59:30 -070097#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
98#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -070099#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h"
Craig Tiller9eb0fde2017-03-31 16:59:30 -0700100#include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h"
Craig Tillerd52e22f2017-04-02 16:22:52 -0700101#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
102#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
103#include "src/core/ext/filters/client_channel/parse_address.h"
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700104#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h"
Juanli Shen6502ecc2017-09-13 13:10:54 -0700105#include "src/core/ext/filters/client_channel/subchannel_index.h"
Craig Tillerc0df1c02017-07-17 16:12:33 -0700106#include "src/core/lib/backoff/backoff.h"
Mark D. Roth046cf762016-09-26 11:13:51 -0700107#include "src/core/lib/channel/channel_args.h"
Mark D. Roth09e458c2017-05-02 08:13:26 -0700108#include "src/core/lib/channel/channel_stack.h"
Craig Tiller2400bf52017-02-09 16:25:19 -0800109#include "src/core/lib/iomgr/combiner.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200110#include "src/core/lib/iomgr/sockaddr.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700111#include "src/core/lib/iomgr/sockaddr_utils.h"
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200112#include "src/core/lib/iomgr/timer.h"
David Garcia Quintas01291502017-02-07 13:26:41 -0800113#include "src/core/lib/slice/slice_hash_table.h"
Craig Tiller18b4ba32016-11-09 15:23:42 -0800114#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -0700115#include "src/core/lib/slice/slice_string_helpers.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"
Mark D. Roth09e458c2017-05-02 08:13:26 -0700119#include "src/core/lib/surface/channel_init.h"
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700120#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700121
David Garcia Quintas1edfb952016-11-22 17:15:34 -0800122#define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20
123#define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1
124#define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6
125#define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120
126#define GRPC_GRPCLB_RECONNECT_JITTER 0.2
Juanli Shenfe408152017-09-27 12:27:20 -0700127#define GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS 10000
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200128
ncteisen06bce6e2017-07-10 07:58:49 -0700129grpc_tracer_flag grpc_lb_glb_trace = GRPC_TRACER_INITIALIZER(false, "glb");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700130
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700131/* add lb_token of selected subchannel (address) to the call's initial
132 * metadata */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700133static grpc_error* initial_metadata_add_lb_token(
134 grpc_exec_ctx* exec_ctx, grpc_metadata_batch* initial_metadata,
135 grpc_linked_mdelem* lb_token_mdelem_storage, grpc_mdelem lb_token) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700136 GPR_ASSERT(lb_token_mdelem_storage != NULL);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800137 GPR_ASSERT(!GRPC_MDISNULL(lb_token));
138 return grpc_metadata_batch_add_tail(exec_ctx, initial_metadata,
139 lb_token_mdelem_storage, lb_token);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700140}
141
Craig Tillerbaa14a92017-11-03 09:09:36 -0700142static void destroy_client_stats(void* arg) {
143 grpc_grpclb_client_stats_unref((grpc_grpclb_client_stats*)arg);
Mark D. Roth09e458c2017-05-02 08:13:26 -0700144}
145
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700146typedef struct wrapped_rr_closure_arg {
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700147 /* the closure instance using this struct as argument */
148 grpc_closure wrapper_closure;
149
David Garcia Quintas43339842016-07-18 12:56:09 -0700150 /* the original closure. Usually a on_complete/notify cb for pick() and ping()
151 * calls against the internal RR instance, respectively. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700152 grpc_closure* wrapped_closure;
David Garcia Quintas43339842016-07-18 12:56:09 -0700153
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700154 /* the pick's initial metadata, kept in order to append the LB token for the
155 * pick */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700156 grpc_metadata_batch* initial_metadata;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700157
158 /* the picked target, used to determine which LB token to add to the pick's
159 * initial metadata */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700160 grpc_connected_subchannel** target;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700161
Mark D. Roth09e458c2017-05-02 08:13:26 -0700162 /* the context to be populated for the subchannel call */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700163 grpc_call_context_element* context;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700164
165 /* Stats for client-side load reporting. Note that this holds a
166 * reference, which must be either passed on via context or unreffed. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700167 grpc_grpclb_client_stats* client_stats;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700168
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700169 /* the LB token associated with the pick */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800170 grpc_mdelem lb_token;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700171
172 /* storage for the lb token initial metadata mdelem */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700173 grpc_linked_mdelem* lb_token_mdelem_storage;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700174
David Garcia Quintas43339842016-07-18 12:56:09 -0700175 /* The RR instance related to the closure */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700176 grpc_lb_policy* rr_policy;
David Garcia Quintas43339842016-07-18 12:56:09 -0700177
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800178 /* The grpclb instance that created the wrapping */
179 grpc_lb_policy* glb_policy;
180
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700181 /* heap memory to be freed upon closure execution. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700182 void* free_when_done;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700183} wrapped_rr_closure_arg;
184
185/* The \a on_complete closure passed as part of the pick requires keeping a
186 * reference to its associated round robin instance. We wrap this closure in
187 * order to unref the round robin instance upon its invocation */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700188static void wrapped_rr_closure(grpc_exec_ctx* exec_ctx, void* arg,
189 grpc_error* error) {
190 wrapped_rr_closure_arg* wc_arg = (wrapped_rr_closure_arg*)arg;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700191
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200192 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
ncteisen969b46e2017-06-08 14:57:11 -0700193 GRPC_CLOSURE_SCHED(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200194
195 if (wc_arg->rr_policy != NULL) {
David Garcia Quintas6493a732016-11-22 10:25:52 -0800196 /* if *target is NULL, no pick has been made by the RR policy (eg, all
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700197 * addresses failed to connect). There won't be any user_data/token
198 * available */
David Garcia Quintas6493a732016-11-22 10:25:52 -0800199 if (*wc_arg->target != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800200 if (!GRPC_MDISNULL(wc_arg->lb_token)) {
201 initial_metadata_add_lb_token(exec_ctx, wc_arg->initial_metadata,
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800202 wc_arg->lb_token_mdelem_storage,
203 GRPC_MDELEM_REF(wc_arg->lb_token));
204 } else {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800205 gpr_log(
206 GPR_ERROR,
207 "[grpclb %p] No LB token for connected subchannel pick %p (from RR "
208 "instance %p).",
209 wc_arg->glb_policy, *wc_arg->target, wc_arg->rr_policy);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800210 abort();
211 }
Mark D. Roth09e458c2017-05-02 08:13:26 -0700212 // Pass on client stats via context. Passes ownership of the reference.
213 GPR_ASSERT(wc_arg->client_stats != NULL);
214 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
215 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
216 } else {
217 grpc_grpclb_client_stats_unref(wc_arg->client_stats);
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700218 }
Craig Tiller84f75d42017-05-03 13:06:35 -0700219 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800220 gpr_log(GPR_INFO, "[grpclb %p] Unreffing RR %p", wc_arg->glb_policy,
221 wc_arg->rr_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200222 }
223 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700224 }
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700225 GPR_ASSERT(wc_arg->free_when_done != NULL);
David Garcia Quintas97ba6422016-10-14 13:06:45 -0700226 gpr_free(wc_arg->free_when_done);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700227}
228
David Garcia Quintasea11d162016-07-14 17:27:28 -0700229/* Linked list of pending pick requests. It stores all information needed to
230 * eventually call (Round Robin's) pick() on them. They mainly stay pending
231 * waiting for the RR policy to be created/updated.
232 *
233 * One particularity is the wrapping of the user-provided \a on_complete closure
234 * (in \a wrapped_on_complete and \a wrapped_on_complete_arg). This is needed in
235 * order to correctly unref the RR policy instance upon completion of the pick.
236 * See \a wrapped_rr_closure for details. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700237typedef struct pending_pick {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700238 struct pending_pick* next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700239
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700240 /* original pick()'s arguments */
241 grpc_lb_policy_pick_args pick_args;
David Garcia Quintas43339842016-07-18 12:56:09 -0700242
243 /* output argument where to store the pick()ed connected subchannel, or NULL
244 * upon error. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700245 grpc_connected_subchannel** target;
David Garcia Quintas43339842016-07-18 12:56:09 -0700246
David Garcia Quintas43339842016-07-18 12:56:09 -0700247 /* args for wrapped_on_complete */
248 wrapped_rr_closure_arg wrapped_on_complete_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700249} pending_pick;
250
Craig Tillerbaa14a92017-11-03 09:09:36 -0700251static void add_pending_pick(pending_pick** root,
252 const grpc_lb_policy_pick_args* pick_args,
253 grpc_connected_subchannel** target,
254 grpc_call_context_element* context,
255 grpc_closure* on_complete) {
256 pending_pick* pp = (pending_pick*)gpr_zalloc(sizeof(*pp));
David Garcia Quintas65318262016-07-29 13:43:38 -0700257 pp->next = *root;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700258 pp->pick_args = *pick_args;
David Garcia Quintas65318262016-07-29 13:43:38 -0700259 pp->target = target;
David Garcia Quintas65318262016-07-29 13:43:38 -0700260 pp->wrapped_on_complete_arg.wrapped_closure = on_complete;
David Garcia Quintas5bb7b9c2016-09-15 23:46:32 -0700261 pp->wrapped_on_complete_arg.target = target;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700262 pp->wrapped_on_complete_arg.context = context;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700263 pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata;
264 pp->wrapped_on_complete_arg.lb_token_mdelem_storage =
265 pick_args->lb_token_mdelem_storage;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700266 pp->wrapped_on_complete_arg.free_when_done = pp;
ncteisen969b46e2017-06-08 14:57:11 -0700267 GRPC_CLOSURE_INIT(&pp->wrapped_on_complete_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800268 wrapped_rr_closure, &pp->wrapped_on_complete_arg,
269 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700270 *root = pp;
271}
272
David Garcia Quintasea11d162016-07-14 17:27:28 -0700273/* Same as the \a pending_pick struct but for ping operations */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700274typedef struct pending_ping {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700275 struct pending_ping* next;
David Garcia Quintas43339842016-07-18 12:56:09 -0700276
David Garcia Quintas43339842016-07-18 12:56:09 -0700277 /* args for wrapped_notify */
278 wrapped_rr_closure_arg wrapped_notify_arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700279} pending_ping;
280
Craig Tillerbaa14a92017-11-03 09:09:36 -0700281static void add_pending_ping(pending_ping** root, grpc_closure* notify) {
282 pending_ping* pping = (pending_ping*)gpr_zalloc(sizeof(*pping));
David Garcia Quintas65318262016-07-29 13:43:38 -0700283 pping->wrapped_notify_arg.wrapped_closure = notify;
David Garcia Quintasb39330d2016-10-14 13:35:56 -0700284 pping->wrapped_notify_arg.free_when_done = pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700285 pping->next = *root;
ncteisen969b46e2017-06-08 14:57:11 -0700286 GRPC_CLOSURE_INIT(&pping->wrapped_notify_arg.wrapper_closure,
Craig Tiller91031da2016-12-28 15:44:25 -0800287 wrapped_rr_closure, &pping->wrapped_notify_arg,
288 grpc_schedule_on_exec_ctx);
David Garcia Quintas65318262016-07-29 13:43:38 -0700289 *root = pping;
290}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700291
David Garcia Quintas8d489112016-07-29 15:20:42 -0700292/*
293 * glb_lb_policy
294 */
David Garcia Quintas65318262016-07-29 13:43:38 -0700295typedef struct rr_connectivity_data rr_connectivity_data;
Yash Tibrewalbc130da2017-09-12 22:44:08 -0700296
David Garcia Quintas65318262016-07-29 13:43:38 -0700297typedef struct glb_lb_policy {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700298 /** base policy: must be first */
299 grpc_lb_policy base;
300
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700301 /** who the client is trying to communicate with */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700302 const char* server_name;
303 grpc_client_channel_factory* cc_factory;
304 grpc_channel_args* args;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700305
Mark D. Roth64d922a2017-05-03 12:52:04 -0700306 /** timeout in milliseconds for the LB call. 0 means no deadline. */
307 int lb_call_timeout_ms;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700308
Juanli Shenfe408152017-09-27 12:27:20 -0700309 /** timeout in milliseconds for before using fallback backend addresses.
310 * 0 means not using fallback. */
311 int lb_fallback_timeout_ms;
312
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700313 /** for communicating with the LB server */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700314 grpc_channel* lb_channel;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700315
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700316 /** response generator to inject address updates into \a lb_channel */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700317 grpc_fake_resolver_response_generator* response_generator;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700318
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700319 /** the RR policy to use of the backend servers returned by the LB server */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700320 grpc_lb_policy* rr_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700321
322 bool started_picking;
323
324 /** our connectivity state tracker */
325 grpc_connectivity_state_tracker state_tracker;
326
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700327 /** connectivity state of the LB channel */
328 grpc_connectivity_state lb_channel_connectivity;
329
David Garcia Quintasea11d162016-07-14 17:27:28 -0700330 /** stores the deserialized response from the LB. May be NULL until one such
331 * response has arrived. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700332 grpc_grpclb_serverlist* serverlist;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700333
Mark D. Rothd7389b42017-05-17 12:22:17 -0700334 /** Index into serverlist for next pick.
335 * If the server at this index is a drop, we return a drop.
336 * Otherwise, we delegate to the RR policy. */
337 size_t serverlist_index;
338
Juanli Shenfe408152017-09-27 12:27:20 -0700339 /** stores the backend addresses from the resolver */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700340 grpc_lb_addresses* fallback_backend_addresses;
Juanli Shenfe408152017-09-27 12:27:20 -0700341
David Garcia Quintasea11d162016-07-14 17:27:28 -0700342 /** list of picks that are waiting on RR's policy connectivity */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700343 pending_pick* pending_picks;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700344
David Garcia Quintasea11d162016-07-14 17:27:28 -0700345 /** list of pings that are waiting on RR's policy connectivity */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700346 pending_ping* pending_pings;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700347
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200348 bool shutting_down;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700349
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700350 /** are we currently updating lb_call? */
351 bool updating_lb_call;
352
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700353 /** are we already watching the LB channel's connectivity? */
354 bool watching_lb_channel;
355
356 /** is \a lb_call_retry_timer active? */
357 bool retry_timer_active;
358
Juanli Shenfe408152017-09-27 12:27:20 -0700359 /** is \a lb_fallback_timer active? */
360 bool fallback_timer_active;
361
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700362 /** called upon changes to the LB channel's connectivity. */
363 grpc_closure lb_channel_on_connectivity_changed;
364
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200365 /************************************************************/
366 /* client data associated with the LB server communication */
367 /************************************************************/
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100368 /* Status from the LB server has been received. This signals the end of the LB
369 * call. */
370 grpc_closure lb_on_server_status_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200371
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100372 /* A response from the LB server has been received. Process it */
373 grpc_closure lb_on_response_received;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200374
Masood Malekghassemib5b43722017-01-05 15:07:26 -0800375 /* LB call retry timer callback. */
376 grpc_closure lb_on_call_retry;
377
Juanli Shenfe408152017-09-27 12:27:20 -0700378 /* LB fallback timer callback. */
379 grpc_closure lb_on_fallback;
380
Craig Tillerbaa14a92017-11-03 09:09:36 -0700381 grpc_call* lb_call; /* streaming call to the LB server, */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200382
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100383 grpc_metadata_array lb_initial_metadata_recv; /* initial MD from LB server */
384 grpc_metadata_array
385 lb_trailing_metadata_recv; /* trailing MD from LB server */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200386
387 /* what's being sent to the LB server. Note that its value may vary if the LB
388 * server indicates a redirect. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700389 grpc_byte_buffer* lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200390
David Garcia Quintas246c5642016-11-01 11:16:52 -0700391 /* response the LB server, if any. Processed in lb_on_response_received() */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700392 grpc_byte_buffer* lb_response_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200393
David Garcia Quintas246c5642016-11-01 11:16:52 -0700394 /* call status code and details, set in lb_on_server_status_received() */
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200395 grpc_status_code lb_call_status;
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800396 grpc_slice lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200397
398 /** LB call retry backoff state */
Craig Tillerc0df1c02017-07-17 16:12:33 -0700399 grpc_backoff lb_call_backoff_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200400
401 /** LB call retry timer */
402 grpc_timer lb_call_retry_timer;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700403
Juanli Shenfe408152017-09-27 12:27:20 -0700404 /** LB fallback timer */
405 grpc_timer lb_fallback_timer;
406
Mark D. Roth09e458c2017-05-02 08:13:26 -0700407 bool seen_initial_response;
408
409 /* Stats for client-side load reporting. Should be unreffed and
410 * recreated whenever lb_call is replaced. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700411 grpc_grpclb_client_stats* client_stats;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700412 /* Interval and timer for next client load report. */
Craig Tillerc0df1c02017-07-17 16:12:33 -0700413 grpc_millis client_stats_report_interval;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700414 grpc_timer client_load_report_timer;
415 bool client_load_report_timer_pending;
416 bool last_client_load_report_counters_were_zero;
417 /* Closure used for either the load report timer or the callback for
418 * completion of sending the load report. */
419 grpc_closure client_load_report_closure;
420 /* Client load report message payload. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700421 grpc_byte_buffer* client_load_report_payload;
David Garcia Quintas65318262016-07-29 13:43:38 -0700422} glb_lb_policy;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700423
David Garcia Quintas65318262016-07-29 13:43:38 -0700424/* Keeps track and reacts to changes in connectivity of the RR instance */
425struct rr_connectivity_data {
426 grpc_closure on_change;
427 grpc_connectivity_state state;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700428 glb_lb_policy* glb_policy;
David Garcia Quintas65318262016-07-29 13:43:38 -0700429};
David Garcia Quintas8d489112016-07-29 15:20:42 -0700430
Craig Tillerbaa14a92017-11-03 09:09:36 -0700431static bool is_server_valid(const grpc_grpclb_server* server, size_t idx,
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700432 bool log) {
Mark D. Rothe7751802017-07-27 12:31:45 -0700433 if (server->drop) return false;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700434 const grpc_grpclb_ip_address* ip = &server->ip_address;
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700435 if (server->port >> 16 != 0) {
436 if (log) {
437 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200438 "Invalid port '%d' at index %lu of serverlist. Ignoring.",
439 server->port, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700440 }
441 return false;
442 }
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700443 if (ip->size != 4 && ip->size != 16) {
444 if (log) {
445 gpr_log(GPR_ERROR,
Jan Tattermusch2b398082016-10-07 14:40:30 +0200446 "Expected IP to be 4 or 16 bytes, got %d at index %lu of "
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700447 "serverlist. Ignoring",
Jan Tattermusch2b398082016-10-07 14:40:30 +0200448 ip->size, (unsigned long)idx);
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700449 }
450 return false;
451 }
452 return true;
453}
454
Mark D. Roth16883a32016-10-21 10:30:58 -0700455/* vtable for LB tokens in grpc_lb_addresses. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700456static void* lb_token_copy(void* token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800457 return token == NULL
458 ? NULL
Craig Tillerbaa14a92017-11-03 09:09:36 -0700459 : (void*)GRPC_MDELEM_REF(grpc_mdelem{(uintptr_t)token}).payload;
Mark D. Roth16883a32016-10-21 10:30:58 -0700460}
Craig Tillerbaa14a92017-11-03 09:09:36 -0700461static void lb_token_destroy(grpc_exec_ctx* exec_ctx, void* token) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800462 if (token != NULL) {
Yash Tibrewald8b84a22017-09-25 13:38:03 -0700463 GRPC_MDELEM_UNREF(exec_ctx, grpc_mdelem{(uintptr_t)token});
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800464 }
Mark D. Roth16883a32016-10-21 10:30:58 -0700465}
Craig Tillerbaa14a92017-11-03 09:09:36 -0700466static int lb_token_cmp(void* token1, void* token2) {
Mark D. Roth16883a32016-10-21 10:30:58 -0700467 if (token1 > token2) return 1;
468 if (token1 < token2) return -1;
469 return 0;
470}
471static const grpc_lb_user_data_vtable lb_token_vtable = {
472 lb_token_copy, lb_token_destroy, lb_token_cmp};
473
Craig Tillerbaa14a92017-11-03 09:09:36 -0700474static void parse_server(const grpc_grpclb_server* server,
475 grpc_resolved_address* addr) {
Mark D. Rothd7389b42017-05-17 12:22:17 -0700476 memset(addr, 0, sizeof(*addr));
Mark D. Rothe7751802017-07-27 12:31:45 -0700477 if (server->drop) return;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100478 const uint16_t netorder_port = htons((uint16_t)server->port);
479 /* the addresses are given in binary format (a in(6)_addr struct) in
480 * server->ip_address.bytes. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700481 const grpc_grpclb_ip_address* ip = &server->ip_address;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100482 if (ip->size == 4) {
483 addr->len = sizeof(struct sockaddr_in);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700484 struct sockaddr_in* addr4 = (struct sockaddr_in*)&addr->addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100485 addr4->sin_family = AF_INET;
486 memcpy(&addr4->sin_addr, ip->bytes, ip->size);
487 addr4->sin_port = netorder_port;
488 } else if (ip->size == 16) {
489 addr->len = sizeof(struct sockaddr_in6);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700490 struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&addr->addr;
David Garcia Quintas107ca162016-11-02 18:17:03 -0700491 addr6->sin6_family = AF_INET6;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100492 memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
493 addr6->sin6_port = netorder_port;
494 }
495}
496
Mark D. Roth7ce14d22016-09-16 13:03:46 -0700497/* Returns addresses extracted from \a serverlist. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700498static grpc_lb_addresses* process_serverlist_locked(
499 grpc_exec_ctx* exec_ctx, const grpc_grpclb_serverlist* serverlist) {
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700500 size_t num_valid = 0;
501 /* first pass: count how many are valid in order to allocate the necessary
502 * memory in a single block */
503 for (size_t i = 0; i < serverlist->num_servers; ++i) {
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700504 if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
David Garcia Quintasb8b384a2016-08-23 21:10:29 -0700505 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700506 grpc_lb_addresses* lb_addresses =
Mark D. Roth16883a32016-10-21 10:30:58 -0700507 grpc_lb_addresses_create(num_valid, &lb_token_vtable);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700508 /* second pass: actually populate the addresses and LB tokens (aka user data
David Garcia Quintas35c2aba2016-09-13 15:28:09 -0700509 * to the outside world) to be read by the RR policy during its creation.
510 * Given that the validity tests are very cheap, they are performed again
511 * instead of marking the valid ones during the first pass, as this would
512 * incurr in an allocation due to the arbitrary number of server */
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700513 size_t addr_idx = 0;
514 for (size_t sl_idx = 0; sl_idx < serverlist->num_servers; ++sl_idx) {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700515 const grpc_grpclb_server* server = serverlist->servers[sl_idx];
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700516 if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
David Garcia Quintasc22c65b2017-07-25 14:22:20 -0700517 GPR_ASSERT(addr_idx < num_valid);
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700518 /* address processing */
Mark D. Rothc5c38782016-09-16 08:51:01 -0700519 grpc_resolved_address addr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +0100520 parse_server(server, &addr);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700521 /* lb token processing */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700522 void* user_data;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700523 if (server->has_load_balance_token) {
David Garcia Quintas0baf1dc2016-10-28 04:44:01 +0200524 const size_t lb_token_max_length =
525 GPR_ARRAY_SIZE(server->load_balance_token);
526 const size_t lb_token_length =
527 strnlen(server->load_balance_token, lb_token_max_length);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800528 grpc_slice lb_token_mdstr = grpc_slice_from_copied_buffer(
529 server->load_balance_token, lb_token_length);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700530 user_data = (void*)grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_LB_TOKEN,
531 lb_token_mdstr)
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800532 .payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700533 } else {
Craig Tillerbaa14a92017-11-03 09:09:36 -0700534 char* uri = grpc_sockaddr_to_uri(&addr);
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800535 gpr_log(GPR_INFO,
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700536 "Missing LB token for backend address '%s'. The empty token will "
537 "be used instead",
David Garcia Quintas850cbaa2016-11-15 15:13:35 -0800538 uri);
539 gpr_free(uri);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700540 user_data = (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload;
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700541 }
Mark D. Rothc5c38782016-09-16 08:51:01 -0700542
Mark D. Roth64f1f8d2016-09-16 09:00:09 -0700543 grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
544 false /* is_balancer */,
Mark D. Rothc5c38782016-09-16 08:51:01 -0700545 NULL /* balancer_name */, user_data);
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700546 ++addr_idx;
David Garcia Quintas331b9c02016-09-12 18:37:05 -0700547 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700548 GPR_ASSERT(addr_idx == num_valid);
Mark D. Rothc5c38782016-09-16 08:51:01 -0700549 return lb_addresses;
550}
551
Juanli Shenfe408152017-09-27 12:27:20 -0700552/* Returns the backend addresses extracted from the given addresses */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700553static grpc_lb_addresses* extract_backend_addresses_locked(
554 grpc_exec_ctx* exec_ctx, const grpc_lb_addresses* addresses) {
Juanli Shenfe408152017-09-27 12:27:20 -0700555 /* first pass: count the number of backend addresses */
556 size_t num_backends = 0;
557 for (size_t i = 0; i < addresses->num_addresses; ++i) {
558 if (!addresses->addresses[i].is_balancer) {
559 ++num_backends;
560 }
561 }
562 /* second pass: actually populate the addresses and (empty) LB tokens */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700563 grpc_lb_addresses* backend_addresses =
Juanli Shenfe408152017-09-27 12:27:20 -0700564 grpc_lb_addresses_create(num_backends, &lb_token_vtable);
565 size_t num_copied = 0;
566 for (size_t i = 0; i < addresses->num_addresses; ++i) {
567 if (addresses->addresses[i].is_balancer) continue;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700568 const grpc_resolved_address* addr = &addresses->addresses[i].address;
Juanli Shenfe408152017-09-27 12:27:20 -0700569 grpc_lb_addresses_set_address(backend_addresses, num_copied, &addr->addr,
570 addr->len, false /* is_balancer */,
571 NULL /* balancer_name */,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700572 (void*)GRPC_MDELEM_LB_TOKEN_EMPTY.payload);
Juanli Shenfe408152017-09-27 12:27:20 -0700573 ++num_copied;
574 }
575 return backend_addresses;
576}
577
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700578static void update_lb_connectivity_status_locked(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700579 grpc_exec_ctx* exec_ctx, glb_lb_policy* glb_policy,
580 grpc_connectivity_state rr_state, grpc_error* rr_state_error) {
Craig Tiller613dafa2017-02-09 12:00:43 -0800581 const grpc_connectivity_state curr_glb_state =
582 grpc_connectivity_state_check(&glb_policy->state_tracker);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800583
584 /* The new connectivity status is a function of the previous one and the new
585 * input coming from the status of the RR policy.
586 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800587 * current state (grpclb's)
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800588 * |
589 * v || I | C | R | TF | SD | <- new state (RR's)
590 * ===++====+=====+=====+======+======+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800591 * I || I | C | R | [I] | [I] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800592 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800593 * C || I | C | R | [C] | [C] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800594 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800595 * R || I | C | R | [R] | [R] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800596 * ---++----+-----+-----+------+------+
David Garcia Quintas4283a262016-11-18 10:43:56 -0800597 * TF || I | C | R | [TF] | [TF] |
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800598 * ---++----+-----+-----+------+------+
599 * SD || NA | NA | NA | NA | NA | (*)
600 * ---++----+-----+-----+------+------+
601 *
David Garcia Quintas4283a262016-11-18 10:43:56 -0800602 * A [STATE] indicates that the old RR policy is kept. In those cases, STATE
603 * is the current state of grpclb, which is left untouched.
604 *
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800605 * In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
606 * the previous RR instance.
607 *
608 * Note that the status is never updated to SHUTDOWN as a result of calling
609 * this function. Only glb_shutdown() has the power to set that state.
610 *
611 * (*) This function mustn't be called during shutting down. */
612 GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
613
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700614 switch (rr_state) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800615 case GRPC_CHANNEL_TRANSIENT_FAILURE:
616 case GRPC_CHANNEL_SHUTDOWN:
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700617 GPR_ASSERT(rr_state_error != GRPC_ERROR_NONE);
618 break;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800619 case GRPC_CHANNEL_IDLE:
620 case GRPC_CHANNEL_CONNECTING:
621 case GRPC_CHANNEL_READY:
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700622 GPR_ASSERT(rr_state_error == GRPC_ERROR_NONE);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800623 }
624
Craig Tiller84f75d42017-05-03 13:06:35 -0700625 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700626 gpr_log(
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800627 GPR_INFO,
628 "[grpclb %p] Setting grpclb's state to %s from new RR policy %p state.",
629 glb_policy, grpc_connectivity_state_name(rr_state),
630 glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800631 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700632 grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, rr_state,
David Garcia Quintasc22c65b2017-07-25 14:22:20 -0700633 rr_state_error,
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800634 "update_lb_connectivity_status_locked");
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800635}
636
Mark D. Rothd7389b42017-05-17 12:22:17 -0700637/* Perform a pick over \a glb_policy->rr_policy. Given that a pick can return
638 * immediately (ignoring its completion callback), we need to perform the
639 * cleanups this callback would otherwise be resposible for.
640 * If \a force_async is true, then we will manually schedule the
641 * completion callback even if the pick is available immediately. */
David Garcia Quintas20359062016-10-15 15:22:51 -0700642static bool pick_from_internal_rr_locked(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700643 grpc_exec_ctx* exec_ctx, glb_lb_policy* glb_policy,
644 const grpc_lb_policy_pick_args* pick_args, bool force_async,
645 grpc_connected_subchannel** target, wrapped_rr_closure_arg* wc_arg) {
Juanli Shenfe408152017-09-27 12:27:20 -0700646 // Check for drops if we are not using fallback backend addresses.
647 if (glb_policy->serverlist != NULL) {
648 // Look at the index into the serverlist to see if we should drop this call.
Craig Tillerbaa14a92017-11-03 09:09:36 -0700649 grpc_grpclb_server* server =
Juanli Shenfe408152017-09-27 12:27:20 -0700650 glb_policy->serverlist->servers[glb_policy->serverlist_index++];
651 if (glb_policy->serverlist_index == glb_policy->serverlist->num_servers) {
652 glb_policy->serverlist_index = 0; // Wrap-around.
Mark D. Rothd7389b42017-05-17 12:22:17 -0700653 }
Juanli Shenfe408152017-09-27 12:27:20 -0700654 if (server->drop) {
655 // Not using the RR policy, so unref it.
656 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800657 gpr_log(GPR_INFO, "[grpclb %p] Unreffing RR %p for drop", glb_policy,
Juanli Shenfe408152017-09-27 12:27:20 -0700658 (intptr_t)wc_arg->rr_policy);
659 }
660 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
661 // Update client load reporting stats to indicate the number of
662 // dropped calls. Note that we have to do this here instead of in
663 // the client_load_reporting filter, because we do not create a
664 // subchannel call (and therefore no client_load_reporting filter)
665 // for dropped calls.
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800666 GPR_ASSERT(wc_arg->client_stats != NULL);
Juanli Shenfe408152017-09-27 12:27:20 -0700667 grpc_grpclb_client_stats_add_call_dropped_locked(
668 server->load_balance_token, wc_arg->client_stats);
669 grpc_grpclb_client_stats_unref(wc_arg->client_stats);
670 if (force_async) {
671 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
672 GRPC_CLOSURE_SCHED(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
673 gpr_free(wc_arg->free_when_done);
674 return false;
675 }
Mark D. Rothd7389b42017-05-17 12:22:17 -0700676 gpr_free(wc_arg->free_when_done);
Juanli Shenfe408152017-09-27 12:27:20 -0700677 return true;
Mark D. Rothd7389b42017-05-17 12:22:17 -0700678 }
Mark D. Rothd7389b42017-05-17 12:22:17 -0700679 }
680 // Pick via the RR policy.
Craig Tiller2400bf52017-02-09 16:25:19 -0800681 const bool pick_done = grpc_lb_policy_pick_locked(
Mark D. Rothd7389b42017-05-17 12:22:17 -0700682 exec_ctx, wc_arg->rr_policy, pick_args, target, wc_arg->context,
Craig Tillerbaa14a92017-11-03 09:09:36 -0700683 (void**)&wc_arg->lb_token, &wc_arg->wrapper_closure);
David Garcia Quintas20359062016-10-15 15:22:51 -0700684 if (pick_done) {
685 /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */
Craig Tiller84f75d42017-05-03 13:06:35 -0700686 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800687 gpr_log(GPR_INFO, "[grpclb %p] Unreffing RR %p", glb_policy,
688 wc_arg->rr_policy);
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700689 }
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200690 GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "glb_pick_sync");
David Garcia Quintas20359062016-10-15 15:22:51 -0700691 /* add the load reporting initial metadata */
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800692 initial_metadata_add_lb_token(exec_ctx, pick_args->initial_metadata,
David Garcia Quintas20359062016-10-15 15:22:51 -0700693 pick_args->lb_token_mdelem_storage,
694 GRPC_MDELEM_REF(wc_arg->lb_token));
Mark D. Roth09e458c2017-05-02 08:13:26 -0700695 // Pass on client stats via context. Passes ownership of the reference.
696 GPR_ASSERT(wc_arg->client_stats != NULL);
697 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats;
698 wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats;
Mark D. Rothd7389b42017-05-17 12:22:17 -0700699 if (force_async) {
700 GPR_ASSERT(wc_arg->wrapped_closure != NULL);
ncteisen969b46e2017-06-08 14:57:11 -0700701 GRPC_CLOSURE_SCHED(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_NONE);
Mark D. Rothd7389b42017-05-17 12:22:17 -0700702 gpr_free(wc_arg->free_when_done);
703 return false;
704 }
Mark D. Roth09e458c2017-05-02 08:13:26 -0700705 gpr_free(wc_arg->free_when_done);
David Garcia Quintas20359062016-10-15 15:22:51 -0700706 }
707 /* else, the pending pick will be registered and taken care of by the
708 * pending pick list inside the RR policy (glb_policy->rr_policy).
709 * Eventually, wrapped_on_complete will be called, which will -among other
710 * things- add the LB token to the call's initial metadata */
David Garcia Quintas20359062016-10-15 15:22:51 -0700711 return pick_done;
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700712}
713
Craig Tillerbaa14a92017-11-03 09:09:36 -0700714static grpc_lb_policy_args* lb_policy_args_create(grpc_exec_ctx* exec_ctx,
715 glb_lb_policy* glb_policy) {
716 grpc_lb_addresses* addresses;
Juanli Shenfe408152017-09-27 12:27:20 -0700717 if (glb_policy->serverlist != NULL) {
718 GPR_ASSERT(glb_policy->serverlist->num_servers > 0);
719 addresses = process_serverlist_locked(exec_ctx, glb_policy->serverlist);
720 } else {
721 // If rr_handover_locked() is invoked when we haven't received any
722 // serverlist from the balancer, we use the fallback backends returned by
723 // the resolver. Note that the fallback backend list may be empty, in which
724 // case the new round_robin policy will keep the requested picks pending.
725 GPR_ASSERT(glb_policy->fallback_backend_addresses != NULL);
726 addresses = grpc_lb_addresses_copy(glb_policy->fallback_backend_addresses);
727 }
David Garcia Quintasc22c65b2017-07-25 14:22:20 -0700728 GPR_ASSERT(addresses != NULL);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700729 grpc_lb_policy_args* args = (grpc_lb_policy_args*)gpr_zalloc(sizeof(*args));
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700730 args->client_channel_factory = glb_policy->cc_factory;
731 args->combiner = glb_policy->base.combiner;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700732 // Replace the LB addresses in the channel args that we pass down to
733 // the subchannel.
Craig Tillerbaa14a92017-11-03 09:09:36 -0700734 static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200735 const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700736 args->args = grpc_channel_args_copy_and_add_and_remove(
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700737 glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
738 1);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800739 grpc_lb_addresses_destroy(exec_ctx, addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700740 return args;
741}
742
Craig Tillerbaa14a92017-11-03 09:09:36 -0700743static void lb_policy_args_destroy(grpc_exec_ctx* exec_ctx,
744 grpc_lb_policy_args* args) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700745 grpc_channel_args_destroy(exec_ctx, args->args);
746 gpr_free(args);
David Garcia Quintas65318262016-07-29 13:43:38 -0700747}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700748
Craig Tillerbaa14a92017-11-03 09:09:36 -0700749static void glb_rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx,
750 void* arg, grpc_error* error);
751static void create_rr_locked(grpc_exec_ctx* exec_ctx, glb_lb_policy* glb_policy,
752 grpc_lb_policy_args* args) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700753 GPR_ASSERT(glb_policy->rr_policy == NULL);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800754
Craig Tillerbaa14a92017-11-03 09:09:36 -0700755 grpc_lb_policy* new_rr_policy =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700756 grpc_lb_policy_create(exec_ctx, "round_robin", args);
David Garcia Quintas4283a262016-11-18 10:43:56 -0800757 if (new_rr_policy == NULL) {
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800758 gpr_log(GPR_ERROR,
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800759 "[grpclb %p] Failure creating a RoundRobin policy for serverlist "
760 "update with %lu entries. The previous RR instance (%p), if any, "
761 "will continue to be used. Future updates from the LB will attempt "
762 "to create new instances.",
763 glb_policy, (unsigned long)glb_policy->serverlist->num_servers,
764 glb_policy->rr_policy);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800765 return;
David Garcia Quintas65318262016-07-29 13:43:38 -0700766 }
David Garcia Quintas4283a262016-11-18 10:43:56 -0800767 glb_policy->rr_policy = new_rr_policy;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700768 grpc_error* rr_state_error = NULL;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700769 const grpc_connectivity_state rr_state =
770 grpc_lb_policy_check_connectivity_locked(exec_ctx, glb_policy->rr_policy,
771 &rr_state_error);
772 /* Connectivity state is a function of the RR policy updated/created */
773 update_lb_connectivity_status_locked(exec_ctx, glb_policy, rr_state,
774 rr_state_error);
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800775 /* Add the gRPC LB's interested_parties pollset_set to that of the newly
776 * created RR policy. This will make the RR policy progress upon activity on
777 * gRPC LB, which in turn is tied to the application's call */
Yuchen Zengb4291642016-09-01 19:17:14 -0700778 grpc_pollset_set_add_pollset_set(exec_ctx,
779 glb_policy->rr_policy->interested_parties,
780 glb_policy->base.interested_parties);
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200781
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800782 /* Allocate the data for the tracking of the new RR policy's connectivity.
783 * It'll be deallocated in glb_rr_connectivity_changed() */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700784 rr_connectivity_data* rr_connectivity =
785 (rr_connectivity_data*)gpr_zalloc(sizeof(rr_connectivity_data));
ncteisen969b46e2017-06-08 14:57:11 -0700786 GRPC_CLOSURE_INIT(&rr_connectivity->on_change,
Craig Tiller2400bf52017-02-09 16:25:19 -0800787 glb_rr_connectivity_changed_locked, rr_connectivity,
Craig Tilleree4b1452017-05-12 10:56:03 -0700788 grpc_combiner_scheduler(glb_policy->base.combiner));
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200789 rr_connectivity->glb_policy = glb_policy;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700790 rr_connectivity->state = rr_state;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200791
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800792 /* Subscribe to changes to the connectivity of the new RR */
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700793 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "glb_rr_connectivity_cb");
Craig Tiller2400bf52017-02-09 16:25:19 -0800794 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
795 &rr_connectivity->state,
796 &rr_connectivity->on_change);
797 grpc_lb_policy_exit_idle_locked(exec_ctx, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700798
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800799 /* Update picks and pings in wait */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700800 pending_pick* pp;
David Garcia Quintas65318262016-07-29 13:43:38 -0700801 while ((pp = glb_policy->pending_picks)) {
802 glb_policy->pending_picks = pp->next;
803 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick");
804 pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy;
Mark D. Roth09e458c2017-05-02 08:13:26 -0700805 pp->wrapped_on_complete_arg.client_stats =
806 grpc_grpclb_client_stats_ref(glb_policy->client_stats);
Craig Tiller84f75d42017-05-03 13:06:35 -0700807 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800808 gpr_log(GPR_INFO,
809 "[grpclb %p] Pending pick about to (async) PICK from RR %p",
810 glb_policy, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700811 }
Mark D. Rothd7389b42017-05-17 12:22:17 -0700812 pick_from_internal_rr_locked(exec_ctx, glb_policy, &pp->pick_args,
813 true /* force_async */, pp->target,
David Garcia Quintas58c18e72016-10-14 15:23:45 -0700814 &pp->wrapped_on_complete_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -0700815 }
816
Craig Tillerbaa14a92017-11-03 09:09:36 -0700817 pending_ping* pping;
David Garcia Quintas65318262016-07-29 13:43:38 -0700818 while ((pping = glb_policy->pending_pings)) {
819 glb_policy->pending_pings = pping->next;
820 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping");
821 pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy;
Craig Tiller84f75d42017-05-03 13:06:35 -0700822 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800823 gpr_log(GPR_INFO, "[grpclb %p] Pending ping about to PING from RR %p",
824 glb_policy, glb_policy->rr_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -0700825 }
Craig Tiller2400bf52017-02-09 16:25:19 -0800826 grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy,
827 &pping->wrapped_notify_arg.wrapper_closure);
David Garcia Quintas65318262016-07-29 13:43:38 -0700828 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700829}
David Garcia Quintas8d489112016-07-29 15:20:42 -0700830
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700831/* glb_policy->rr_policy may be NULL (initial handover) */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700832static void rr_handover_locked(grpc_exec_ctx* exec_ctx,
833 glb_lb_policy* glb_policy) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700834 if (glb_policy->shutting_down) return;
Craig Tillerbaa14a92017-11-03 09:09:36 -0700835 grpc_lb_policy_args* args = lb_policy_args_create(exec_ctx, glb_policy);
David Garcia Quintasc22c65b2017-07-25 14:22:20 -0700836 GPR_ASSERT(args != NULL);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700837 if (glb_policy->rr_policy != NULL) {
838 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800839 gpr_log(GPR_DEBUG, "[grpclb %p] Updating RR policy %p", glb_policy,
840 glb_policy->rr_policy);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700841 }
842 grpc_lb_policy_update_locked(exec_ctx, glb_policy->rr_policy, args);
843 } else {
844 create_rr_locked(exec_ctx, glb_policy, args);
845 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -0800846 gpr_log(GPR_DEBUG, "[grpclb %p] Created new RR policy %p", glb_policy,
847 glb_policy->rr_policy);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700848 }
849 }
850 lb_policy_args_destroy(exec_ctx, args);
851}
852
Craig Tillerbaa14a92017-11-03 09:09:36 -0700853static void glb_rr_connectivity_changed_locked(grpc_exec_ctx* exec_ctx,
854 void* arg, grpc_error* error) {
855 rr_connectivity_data* rr_connectivity = (rr_connectivity_data*)arg;
856 glb_lb_policy* glb_policy = rr_connectivity->glb_policy;
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700857 if (glb_policy->shutting_down) {
David Garcia Quintas4283a262016-11-18 10:43:56 -0800858 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700859 "glb_rr_connectivity_cb");
860 gpr_free(rr_connectivity);
861 return;
David Garcia Quintas149f09d2016-11-17 20:43:10 -0800862 }
David Garcia Quintasfc950fb2017-07-27 19:41:12 -0700863 if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN) {
864 /* An RR policy that has transitioned into the SHUTDOWN connectivity state
865 * should not be considered for picks or updates: the SHUTDOWN state is a
866 * sink, policies can't transition back from it. .*/
867 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy,
868 "rr_connectivity_shutdown");
869 glb_policy->rr_policy = NULL;
870 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
871 "glb_rr_connectivity_cb");
872 gpr_free(rr_connectivity);
873 return;
874 }
875 /* rr state != SHUTDOWN && !glb_policy->shutting down: biz as usual */
876 update_lb_connectivity_status_locked(
877 exec_ctx, glb_policy, rr_connectivity->state, GRPC_ERROR_REF(error));
878 /* Resubscribe. Reuse the "glb_rr_connectivity_cb" weak ref. */
879 grpc_lb_policy_notify_on_state_change_locked(exec_ctx, glb_policy->rr_policy,
880 &rr_connectivity->state,
881 &rr_connectivity->on_change);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700882}
883
Craig Tillerbaa14a92017-11-03 09:09:36 -0700884static void destroy_balancer_name(grpc_exec_ctx* exec_ctx,
885 void* balancer_name) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800886 gpr_free(balancer_name);
887}
888
David Garcia Quintas01291502017-02-07 13:26:41 -0800889static grpc_slice_hash_table_entry targets_info_entry_create(
Craig Tillerbaa14a92017-11-03 09:09:36 -0700890 const char* address, const char* balancer_name) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800891 grpc_slice_hash_table_entry entry;
892 entry.key = grpc_slice_from_copied_string(address);
Mark D. Rothe3006702017-04-19 07:43:56 -0700893 entry.value = gpr_strdup(balancer_name);
David Garcia Quintas01291502017-02-07 13:26:41 -0800894 return entry;
895}
896
Craig Tillerbaa14a92017-11-03 09:09:36 -0700897static int balancer_name_cmp_fn(void* a, void* b) {
898 const char* a_str = (const char*)a;
899 const char* b_str = (const char*)b;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700900 return strcmp(a_str, b_str);
901}
902
903/* Returns the channel args for the LB channel, used to create a bidirectional
904 * stream for the reception of load balancing updates.
David Garcia Quintas01291502017-02-07 13:26:41 -0800905 *
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700906 * Inputs:
907 * - \a addresses: corresponding to the balancers.
908 * - \a response_generator: in order to propagate updates from the resolver
909 * above the grpclb policy.
910 * - \a args: other args inherited from the grpclb policy. */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700911static grpc_channel_args* build_lb_channel_args(
912 grpc_exec_ctx* exec_ctx, const grpc_lb_addresses* addresses,
913 grpc_fake_resolver_response_generator* response_generator,
914 const grpc_channel_args* args) {
David Garcia Quintas01291502017-02-07 13:26:41 -0800915 size_t num_grpclb_addrs = 0;
916 for (size_t i = 0; i < addresses->num_addresses; ++i) {
917 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
918 }
919 /* All input addresses come from a resolver that claims they are LB services.
920 * It's the resolver's responsibility to make sure this policy is only
921 * instantiated and used in that case. Otherwise, something has gone wrong. */
922 GPR_ASSERT(num_grpclb_addrs > 0);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700923 grpc_lb_addresses* lb_addresses =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700924 grpc_lb_addresses_create(num_grpclb_addrs, NULL);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700925 grpc_slice_hash_table_entry* targets_info_entries =
926 (grpc_slice_hash_table_entry*)gpr_zalloc(sizeof(*targets_info_entries) *
927 num_grpclb_addrs);
David Garcia Quintas01291502017-02-07 13:26:41 -0800928
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700929 size_t lb_addresses_idx = 0;
930 for (size_t i = 0; i < addresses->num_addresses; ++i) {
931 if (!addresses->addresses[i].is_balancer) continue;
David Garcia Quintas01291502017-02-07 13:26:41 -0800932 if (addresses->addresses[i].user_data != NULL) {
933 gpr_log(GPR_ERROR,
934 "This LB policy doesn't support user data. It will be ignored");
935 }
Craig Tillerbaa14a92017-11-03 09:09:36 -0700936 char* addr_str;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700937 GPR_ASSERT(grpc_sockaddr_to_string(
938 &addr_str, &addresses->addresses[i].address, true) > 0);
939 targets_info_entries[lb_addresses_idx] = targets_info_entry_create(
940 addr_str, addresses->addresses[i].balancer_name);
941 gpr_free(addr_str);
942
943 grpc_lb_addresses_set_address(
944 lb_addresses, lb_addresses_idx++, addresses->addresses[i].address.addr,
945 addresses->addresses[i].address.len, false /* is balancer */,
946 addresses->addresses[i].balancer_name, NULL /* user data */);
David Garcia Quintas01291502017-02-07 13:26:41 -0800947 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700948 GPR_ASSERT(num_grpclb_addrs == lb_addresses_idx);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700949 grpc_slice_hash_table* targets_info =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700950 grpc_slice_hash_table_create(num_grpclb_addrs, targets_info_entries,
951 destroy_balancer_name, balancer_name_cmp_fn);
David Garcia Quintas01291502017-02-07 13:26:41 -0800952 gpr_free(targets_info_entries);
953
Craig Tillerbaa14a92017-11-03 09:09:36 -0700954 grpc_channel_args* lb_channel_args =
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700955 grpc_lb_policy_grpclb_build_lb_channel_args(exec_ctx, targets_info,
956 response_generator, args);
957
958 grpc_arg lb_channel_addresses_arg =
959 grpc_lb_addresses_create_channel_arg(lb_addresses);
960
Craig Tillerbaa14a92017-11-03 09:09:36 -0700961 grpc_channel_args* result = grpc_channel_args_copy_and_add(
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700962 lb_channel_args, &lb_channel_addresses_arg, 1);
963 grpc_slice_hash_table_unref(exec_ctx, targets_info);
964 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
965 grpc_lb_addresses_destroy(exec_ctx, lb_addresses);
966 return result;
David Garcia Quintas01291502017-02-07 13:26:41 -0800967}
968
Craig Tillerbaa14a92017-11-03 09:09:36 -0700969static void glb_destroy(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
970 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -0700971 GPR_ASSERT(glb_policy->pending_picks == NULL);
972 GPR_ASSERT(glb_policy->pending_pings == NULL);
Craig Tillerbaa14a92017-11-03 09:09:36 -0700973 gpr_free((void*)glb_policy->server_name);
Craig Tiller87a7e1f2016-11-09 09:42:19 -0800974 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
Mark D. Roth09e458c2017-05-02 08:13:26 -0700975 if (glb_policy->client_stats != NULL) {
976 grpc_grpclb_client_stats_unref(glb_policy->client_stats);
977 }
David Garcia Quintas65318262016-07-29 13:43:38 -0700978 grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker);
979 if (glb_policy->serverlist != NULL) {
980 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
981 }
Juanli Shenfe408152017-09-27 12:27:20 -0700982 if (glb_policy->fallback_backend_addresses != NULL) {
983 grpc_lb_addresses_destroy(exec_ctx, glb_policy->fallback_backend_addresses);
984 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700985 grpc_fake_resolver_response_generator_unref(glb_policy->response_generator);
Juanli Shen6502ecc2017-09-13 13:10:54 -0700986 grpc_subchannel_index_unref();
David Garcia Quintas65318262016-07-29 13:43:38 -0700987 gpr_free(glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700988}
989
Craig Tillerbaa14a92017-11-03 09:09:36 -0700990static void glb_shutdown_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
991 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas98da61b2016-10-29 08:46:31 +0200992 glb_policy->shutting_down = true;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -0700993
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800994 /* We need a copy of the lb_call pointer because we can't cancell the call
995 * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
996 * the cancel, needs to acquire that same lock */
Craig Tillerbaa14a92017-11-03 09:09:36 -0700997 grpc_call* lb_call = glb_policy->lb_call;
David Garcia Quintas65318262016-07-29 13:43:38 -0700998
David Garcia Quintasa74b2462016-11-11 14:07:27 -0800999 /* glb_policy->lb_call and this local lb_call must be consistent at this point
1000 * because glb_policy->lb_call is only assigned in lb_call_init_locked as part
1001 * of query_for_backends_locked, which can only be invoked while
1002 * glb_policy->shutting_down is false. */
1003 if (lb_call != NULL) {
1004 grpc_call_cancel(lb_call, NULL);
1005 /* lb_on_server_status_received will pick up the cancel and clean up */
1006 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001007 if (glb_policy->retry_timer_active) {
1008 grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
1009 glb_policy->retry_timer_active = false;
1010 }
Juanli Shen663f50c2017-10-05 14:36:13 -07001011 if (glb_policy->fallback_timer_active) {
1012 grpc_timer_cancel(exec_ctx, &glb_policy->lb_fallback_timer);
1013 glb_policy->fallback_timer_active = false;
1014 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001015
Craig Tillerbaa14a92017-11-03 09:09:36 -07001016 pending_pick* pp = glb_policy->pending_picks;
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001017 glb_policy->pending_picks = NULL;
Craig Tillerbaa14a92017-11-03 09:09:36 -07001018 pending_ping* pping = glb_policy->pending_pings;
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001019 glb_policy->pending_pings = NULL;
David Garcia Quintasfc950fb2017-07-27 19:41:12 -07001020 if (glb_policy->rr_policy != NULL) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001021 GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "glb_shutdown");
1022 }
1023 // We destroy the LB channel here because
1024 // glb_lb_channel_on_connectivity_changed_cb needs a valid glb_policy
1025 // instance. Destroying the lb channel in glb_destroy would likely result in
1026 // a callback invocation without a valid glb_policy arg.
1027 if (glb_policy->lb_channel != NULL) {
1028 grpc_channel_destroy(glb_policy->lb_channel);
1029 glb_policy->lb_channel = NULL;
1030 }
1031 grpc_connectivity_state_set(
1032 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_SHUTDOWN,
1033 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"), "glb_shutdown");
1034
David Garcia Quintas65318262016-07-29 13:43:38 -07001035 while (pp != NULL) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001036 pending_pick* next = pp->next;
David Garcia Quintas65318262016-07-29 13:43:38 -07001037 *pp->target = NULL;
Mark D. Roth8ba4bf42017-10-05 13:16:33 -07001038 GRPC_CLOSURE_SCHED(
1039 exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
1040 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"));
Mark D. Roth7a2db962017-10-06 15:06:12 -07001041 gpr_free(pp);
David Garcia Quintas65318262016-07-29 13:43:38 -07001042 pp = next;
1043 }
1044
1045 while (pping != NULL) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001046 pending_ping* next = pping->next;
Mark D. Roth8ba4bf42017-10-05 13:16:33 -07001047 GRPC_CLOSURE_SCHED(
1048 exec_ctx, &pping->wrapped_notify_arg.wrapper_closure,
1049 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Shutdown"));
Mark D. Roth7a2db962017-10-06 15:06:12 -07001050 gpr_free(pping);
David Garcia Quintas65318262016-07-29 13:43:38 -07001051 pping = next;
1052 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001053}
1054
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001055// Cancel a specific pending pick.
1056//
1057// A grpclb pick progresses as follows:
1058// - If there's a Round Robin policy (glb_policy->rr_policy) available, it'll be
1059// handed over to the RR policy (in create_rr_locked()). From that point
1060// onwards, it'll be RR's responsibility. For cancellations, that implies the
1061// pick needs also be cancelled by the RR instance.
1062// - Otherwise, without an RR instance, picks stay pending at this policy's
1063// level (grpclb), inside the glb_policy->pending_picks list. To cancel these,
1064// we invoke the completion closure and set *target to NULL right here.
Craig Tillerbaa14a92017-11-03 09:09:36 -07001065static void glb_cancel_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1066 grpc_connected_subchannel** target,
1067 grpc_error* error) {
1068 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
1069 pending_pick* pp = glb_policy->pending_picks;
David Garcia Quintas65318262016-07-29 13:43:38 -07001070 glb_policy->pending_picks = NULL;
1071 while (pp != NULL) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001072 pending_pick* next = pp->next;
David Garcia Quintas65318262016-07-29 13:43:38 -07001073 if (pp->target == target) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001074 *target = NULL;
ncteisen969b46e2017-06-08 14:57:11 -07001075 GRPC_CLOSURE_SCHED(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
ncteisen4b36a3d2017-03-13 19:08:06 -07001076 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1077 "Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -07001078 } else {
1079 pp->next = glb_policy->pending_picks;
1080 glb_policy->pending_picks = pp;
1081 }
1082 pp = next;
1083 }
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001084 if (glb_policy->rr_policy != NULL) {
1085 grpc_lb_policy_cancel_pick_locked(exec_ctx, glb_policy->rr_policy, target,
1086 GRPC_ERROR_REF(error));
1087 }
Mark D. Roth5f844002016-09-08 08:20:53 -07001088 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001089}
1090
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001091// Cancel all pending picks.
1092//
1093// A grpclb pick progresses as follows:
1094// - If there's a Round Robin policy (glb_policy->rr_policy) available, it'll be
1095// handed over to the RR policy (in create_rr_locked()). From that point
1096// onwards, it'll be RR's responsibility. For cancellations, that implies the
1097// pick needs also be cancelled by the RR instance.
1098// - Otherwise, without an RR instance, picks stay pending at this policy's
1099// level (grpclb), inside the glb_policy->pending_picks list. To cancel these,
1100// we invoke the completion closure and set *target to NULL right here.
Craig Tillerbaa14a92017-11-03 09:09:36 -07001101static void glb_cancel_picks_locked(grpc_exec_ctx* exec_ctx,
1102 grpc_lb_policy* pol,
Craig Tiller2400bf52017-02-09 16:25:19 -08001103 uint32_t initial_metadata_flags_mask,
1104 uint32_t initial_metadata_flags_eq,
Craig Tillerbaa14a92017-11-03 09:09:36 -07001105 grpc_error* error) {
1106 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
1107 pending_pick* pp = glb_policy->pending_picks;
David Garcia Quintas65318262016-07-29 13:43:38 -07001108 glb_policy->pending_picks = NULL;
1109 while (pp != NULL) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001110 pending_pick* next = pp->next;
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001111 if ((pp->pick_args.initial_metadata_flags & initial_metadata_flags_mask) ==
David Garcia Quintas65318262016-07-29 13:43:38 -07001112 initial_metadata_flags_eq) {
ncteisen969b46e2017-06-08 14:57:11 -07001113 GRPC_CLOSURE_SCHED(exec_ctx, &pp->wrapped_on_complete_arg.wrapper_closure,
ncteisen4b36a3d2017-03-13 19:08:06 -07001114 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1115 "Pick Cancelled", &error, 1));
David Garcia Quintas65318262016-07-29 13:43:38 -07001116 } else {
1117 pp->next = glb_policy->pending_picks;
1118 glb_policy->pending_picks = pp;
1119 }
1120 pp = next;
1121 }
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001122 if (glb_policy->rr_policy != NULL) {
1123 grpc_lb_policy_cancel_picks_locked(
1124 exec_ctx, glb_policy->rr_policy, initial_metadata_flags_mask,
1125 initial_metadata_flags_eq, GRPC_ERROR_REF(error));
1126 }
Mark D. Rothe65ff112016-09-09 13:48:38 -07001127 GRPC_ERROR_UNREF(error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001128}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001129
Craig Tillerbaa14a92017-11-03 09:09:36 -07001130static void lb_on_fallback_timer_locked(grpc_exec_ctx* exec_ctx, void* arg,
1131 grpc_error* error);
1132static void query_for_backends_locked(grpc_exec_ctx* exec_ctx,
1133 glb_lb_policy* glb_policy);
1134static void start_picking_locked(grpc_exec_ctx* exec_ctx,
1135 glb_lb_policy* glb_policy) {
Juanli Shenfe408152017-09-27 12:27:20 -07001136 /* start a timer to fall back */
1137 if (glb_policy->lb_fallback_timeout_ms > 0 &&
1138 glb_policy->serverlist == NULL && !glb_policy->fallback_timer_active) {
Craig Tiller1e868f02017-09-29 11:18:26 -07001139 grpc_millis deadline =
1140 grpc_exec_ctx_now(exec_ctx) + glb_policy->lb_fallback_timeout_ms;
Juanli Shenfe408152017-09-27 12:27:20 -07001141 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_fallback_timer");
1142 GRPC_CLOSURE_INIT(&glb_policy->lb_on_fallback, lb_on_fallback_timer_locked,
1143 glb_policy,
1144 grpc_combiner_scheduler(glb_policy->base.combiner));
1145 glb_policy->fallback_timer_active = true;
1146 grpc_timer_init(exec_ctx, &glb_policy->lb_fallback_timer, deadline,
Craig Tiller1e868f02017-09-29 11:18:26 -07001147 &glb_policy->lb_on_fallback);
Juanli Shenfe408152017-09-27 12:27:20 -07001148 }
1149
David Garcia Quintas65318262016-07-29 13:43:38 -07001150 glb_policy->started_picking = true;
Craig Tillerc0df1c02017-07-17 16:12:33 -07001151 grpc_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001152 query_for_backends_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001153}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001154
Craig Tillerbaa14a92017-11-03 09:09:36 -07001155static void glb_exit_idle_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol) {
1156 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001157 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001158 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001159 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001160}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001161
Craig Tillerbaa14a92017-11-03 09:09:36 -07001162static int glb_pick_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1163 const grpc_lb_policy_pick_args* pick_args,
1164 grpc_connected_subchannel** target,
1165 grpc_call_context_element* context, void** user_data,
1166 grpc_closure* on_complete) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001167 if (pick_args->lb_token_mdelem_storage == NULL) {
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001168 *target = NULL;
ncteisen969b46e2017-06-08 14:57:11 -07001169 GRPC_CLOSURE_SCHED(exec_ctx, on_complete,
ncteisen4b36a3d2017-03-13 19:08:06 -07001170 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1171 "No mdelem storage for the LB token. Load reporting "
1172 "won't work without it. Failing"));
Mark D. Roth1e5f6af2016-10-07 08:32:58 -07001173 return 0;
David Garcia Quintas5b0e9462016-08-15 19:38:39 -07001174 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001175 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001176 bool pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001177 if (glb_policy->rr_policy != NULL) {
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001178 const grpc_connectivity_state rr_connectivity_state =
1179 grpc_lb_policy_check_connectivity_locked(exec_ctx,
1180 glb_policy->rr_policy, NULL);
David Garcia Quintasf6c6b922017-11-03 07:48:16 -07001181 // The glb_policy->rr_policy may have transitioned to SHUTDOWN but the
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001182 // callback registered to capture this event
1183 // (glb_rr_connectivity_changed_locked) may not have been invoked yet. We
1184 // need to make sure we aren't trying to pick from a RR policy instance
1185 // that's in shutdown.
1186 if (rr_connectivity_state == GRPC_CHANNEL_SHUTDOWN) {
1187 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
1188 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001189 "[grpclb %p] NOT picking from from RR %p: RR conn state=%s",
1190 glb_policy, glb_policy->rr_policy,
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001191 grpc_connectivity_state_name(rr_connectivity_state));
1192 }
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001193 add_pending_pick(&glb_policy->pending_picks, pick_args, target, context,
1194 on_complete);
1195 pick_done = false;
1196 } else { // RR not in shutdown
1197 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001198 gpr_log(GPR_INFO, "[grpclb %p] about to PICK from RR %p", glb_policy,
1199 glb_policy->rr_policy);
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001200 }
1201 GRPC_LB_POLICY_REF(glb_policy->rr_policy, "glb_pick");
Craig Tiller34992a62017-11-06 12:33:42 -08001202 wrapped_rr_closure_arg* wc_arg =
1203 (wrapped_rr_closure_arg*)gpr_zalloc(sizeof(wrapped_rr_closure_arg));
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001204 GRPC_CLOSURE_INIT(&wc_arg->wrapper_closure, wrapped_rr_closure, wc_arg,
1205 grpc_schedule_on_exec_ctx);
1206 wc_arg->rr_policy = glb_policy->rr_policy;
1207 wc_arg->target = target;
1208 wc_arg->context = context;
1209 GPR_ASSERT(glb_policy->client_stats != NULL);
1210 wc_arg->client_stats =
1211 grpc_grpclb_client_stats_ref(glb_policy->client_stats);
1212 wc_arg->wrapped_closure = on_complete;
1213 wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage;
1214 wc_arg->initial_metadata = pick_args->initial_metadata;
1215 wc_arg->free_when_done = wc_arg;
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001216 wc_arg->glb_policy = glb_policy;
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001217 pick_done =
1218 pick_from_internal_rr_locked(exec_ctx, glb_policy, pick_args,
1219 false /* force_async */, target, wc_arg);
David Garcia Quintas65318262016-07-29 13:43:38 -07001220 }
David Garcia Quintas2a95bf42017-09-07 11:26:34 -07001221 } else { // glb_policy->rr_policy == NULL
Craig Tiller84f75d42017-05-03 13:06:35 -07001222 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001223 gpr_log(GPR_DEBUG,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001224 "[grpclb %p] No RR policy. Adding to grpclb's pending picks",
1225 glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001226 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001227 add_pending_pick(&glb_policy->pending_picks, pick_args, target, context,
David Garcia Quintas8aace512016-08-15 14:55:12 -07001228 on_complete);
David Garcia Quintas65318262016-07-29 13:43:38 -07001229 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001230 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001231 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001232 pick_done = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001233 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -07001234 return pick_done;
David Garcia Quintas65318262016-07-29 13:43:38 -07001235}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001236
Craig Tiller2400bf52017-02-09 16:25:19 -08001237static grpc_connectivity_state glb_check_connectivity_locked(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001238 grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1239 grpc_error** connectivity_error) {
1240 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
Craig Tiller2400bf52017-02-09 16:25:19 -08001241 return grpc_connectivity_state_get(&glb_policy->state_tracker,
1242 connectivity_error);
David Garcia Quintas65318262016-07-29 13:43:38 -07001243}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001244
Craig Tillerbaa14a92017-11-03 09:09:36 -07001245static void glb_ping_one_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* pol,
1246 grpc_closure* closure) {
1247 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001248 if (glb_policy->rr_policy) {
Craig Tiller2400bf52017-02-09 16:25:19 -08001249 grpc_lb_policy_ping_one_locked(exec_ctx, glb_policy->rr_policy, closure);
David Garcia Quintas65318262016-07-29 13:43:38 -07001250 } else {
1251 add_pending_ping(&glb_policy->pending_pings, closure);
1252 if (!glb_policy->started_picking) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001253 start_picking_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001254 }
1255 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001256}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001257
Craig Tillerbaa14a92017-11-03 09:09:36 -07001258static void glb_notify_on_state_change_locked(grpc_exec_ctx* exec_ctx,
1259 grpc_lb_policy* pol,
1260 grpc_connectivity_state* current,
1261 grpc_closure* notify) {
1262 glb_lb_policy* glb_policy = (glb_lb_policy*)pol;
David Garcia Quintas65318262016-07-29 13:43:38 -07001263 grpc_connectivity_state_notify_on_state_change(
1264 exec_ctx, &glb_policy->state_tracker, current, notify);
David Garcia Quintas65318262016-07-29 13:43:38 -07001265}
1266
Craig Tillerbaa14a92017-11-03 09:09:36 -07001267static void lb_call_on_retry_timer_locked(grpc_exec_ctx* exec_ctx, void* arg,
1268 grpc_error* error) {
1269 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Mark D. Rotha4792f52017-09-26 09:06:35 -07001270 glb_policy->retry_timer_active = false;
1271 if (!glb_policy->shutting_down && error == GRPC_ERROR_NONE) {
1272 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001273 gpr_log(GPR_INFO, "[grpclb %p] Restaring call to LB server", glb_policy);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001274 }
1275 GPR_ASSERT(glb_policy->lb_call == NULL);
1276 query_for_backends_locked(exec_ctx, glb_policy);
1277 }
1278 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, "grpclb_retry_timer");
1279}
1280
Craig Tillerbaa14a92017-11-03 09:09:36 -07001281static void maybe_restart_lb_call(grpc_exec_ctx* exec_ctx,
1282 glb_lb_policy* glb_policy) {
Mark D. Rotha4792f52017-09-26 09:06:35 -07001283 if (glb_policy->started_picking && glb_policy->updating_lb_call) {
1284 if (glb_policy->retry_timer_active) {
1285 grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
1286 }
1287 if (!glb_policy->shutting_down) start_picking_locked(exec_ctx, glb_policy);
1288 glb_policy->updating_lb_call = false;
1289 } else if (!glb_policy->shutting_down) {
1290 /* if we aren't shutting down, restart the LB client call after some time */
Craig Tiller1e868f02017-09-29 11:18:26 -07001291 grpc_millis next_try =
David Garcia Quintaseca25f32017-11-02 14:52:54 -07001292 grpc_backoff_step(exec_ctx, &glb_policy->lb_call_backoff_state)
1293 .next_attempt_start_time;
Mark D. Rotha4792f52017-09-26 09:06:35 -07001294 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001295 gpr_log(GPR_DEBUG, "[grpclb %p] Connection to LB server lost...",
1296 glb_policy);
Craig Tiller1e868f02017-09-29 11:18:26 -07001297 grpc_millis timeout = next_try - grpc_exec_ctx_now(exec_ctx);
1298 if (timeout > 0) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001299 gpr_log(GPR_DEBUG,
1300 "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.",
1301 glb_policy, timeout);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001302 } else {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001303 gpr_log(GPR_DEBUG, "[grpclb %p] ... retry_timer_active immediately.",
1304 glb_policy);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001305 }
1306 }
1307 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "grpclb_retry_timer");
1308 GRPC_CLOSURE_INIT(&glb_policy->lb_on_call_retry,
1309 lb_call_on_retry_timer_locked, glb_policy,
1310 grpc_combiner_scheduler(glb_policy->base.combiner));
1311 glb_policy->retry_timer_active = true;
1312 grpc_timer_init(exec_ctx, &glb_policy->lb_call_retry_timer, next_try,
Craig Tiller1e868f02017-09-29 11:18:26 -07001313 &glb_policy->lb_on_call_retry);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001314 }
1315 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1316 "lb_on_server_status_received_locked");
1317}
1318
Craig Tillerbaa14a92017-11-03 09:09:36 -07001319static void send_client_load_report_locked(grpc_exec_ctx* exec_ctx, void* arg,
1320 grpc_error* error);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001321
Craig Tillerbaa14a92017-11-03 09:09:36 -07001322static void schedule_next_client_load_report(grpc_exec_ctx* exec_ctx,
1323 glb_lb_policy* glb_policy) {
Craig Tillerc0df1c02017-07-17 16:12:33 -07001324 const grpc_millis next_client_load_report_time =
1325 grpc_exec_ctx_now(exec_ctx) + glb_policy->client_stats_report_interval;
ncteisen969b46e2017-06-08 14:57:11 -07001326 GRPC_CLOSURE_INIT(&glb_policy->client_load_report_closure,
Mark D. Roth09e458c2017-05-02 08:13:26 -07001327 send_client_load_report_locked, glb_policy,
Craig Tilleree4b1452017-05-12 10:56:03 -07001328 grpc_combiner_scheduler(glb_policy->base.combiner));
Mark D. Roth09e458c2017-05-02 08:13:26 -07001329 grpc_timer_init(exec_ctx, &glb_policy->client_load_report_timer,
1330 next_client_load_report_time,
Craig Tillerc0df1c02017-07-17 16:12:33 -07001331 &glb_policy->client_load_report_closure);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001332}
1333
Craig Tillerbaa14a92017-11-03 09:09:36 -07001334static void client_load_report_done_locked(grpc_exec_ctx* exec_ctx, void* arg,
1335 grpc_error* error) {
1336 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001337 grpc_byte_buffer_destroy(glb_policy->client_load_report_payload);
1338 glb_policy->client_load_report_payload = NULL;
1339 if (error != GRPC_ERROR_NONE || glb_policy->lb_call == NULL) {
1340 glb_policy->client_load_report_timer_pending = false;
1341 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1342 "client_load_report");
1343 return;
1344 }
1345 schedule_next_client_load_report(exec_ctx, glb_policy);
1346}
1347
Craig Tillerbaa14a92017-11-03 09:09:36 -07001348static bool load_report_counters_are_zero(grpc_grpclb_request* request) {
1349 grpc_grpclb_dropped_call_counts* drop_entries =
1350 (grpc_grpclb_dropped_call_counts*)
Yash Tibrewalbc130da2017-09-12 22:44:08 -07001351 request->client_stats.calls_finished_with_drop.arg;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001352 return request->client_stats.num_calls_started == 0 &&
1353 request->client_stats.num_calls_finished == 0 &&
Mark D. Roth09e458c2017-05-02 08:13:26 -07001354 request->client_stats.num_calls_finished_with_client_failed_to_send ==
1355 0 &&
Mark D. Rothe7751802017-07-27 12:31:45 -07001356 request->client_stats.num_calls_finished_known_received == 0 &&
1357 (drop_entries == NULL || drop_entries->num_entries == 0);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001358}
1359
Craig Tillerbaa14a92017-11-03 09:09:36 -07001360static void send_client_load_report_locked(grpc_exec_ctx* exec_ctx, void* arg,
1361 grpc_error* error) {
1362 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001363 if (error == GRPC_ERROR_CANCELLED || glb_policy->lb_call == NULL) {
1364 glb_policy->client_load_report_timer_pending = false;
1365 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1366 "client_load_report");
Mark D. Rotha4792f52017-09-26 09:06:35 -07001367 if (glb_policy->lb_call == NULL) {
1368 maybe_restart_lb_call(exec_ctx, glb_policy);
1369 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001370 return;
1371 }
1372 // Construct message payload.
1373 GPR_ASSERT(glb_policy->client_load_report_payload == NULL);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001374 grpc_grpclb_request* request =
Mark D. Rothe7751802017-07-27 12:31:45 -07001375 grpc_grpclb_load_report_request_create_locked(glb_policy->client_stats);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001376 // Skip client load report if the counters were all zero in the last
1377 // report and they are still zero in this one.
1378 if (load_report_counters_are_zero(request)) {
1379 if (glb_policy->last_client_load_report_counters_were_zero) {
1380 grpc_grpclb_request_destroy(request);
1381 schedule_next_client_load_report(exec_ctx, glb_policy);
1382 return;
1383 }
1384 glb_policy->last_client_load_report_counters_were_zero = true;
1385 } else {
1386 glb_policy->last_client_load_report_counters_were_zero = false;
1387 }
1388 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
1389 glb_policy->client_load_report_payload =
1390 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
1391 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
1392 grpc_grpclb_request_destroy(request);
Mark D. Roth2de36a82017-09-25 14:54:44 -07001393 // Send load report message.
1394 grpc_op op;
1395 memset(&op, 0, sizeof(op));
1396 op.op = GRPC_OP_SEND_MESSAGE;
1397 op.data.send_message.send_message = glb_policy->client_load_report_payload;
1398 GRPC_CLOSURE_INIT(&glb_policy->client_load_report_closure,
1399 client_load_report_done_locked, glb_policy,
1400 grpc_combiner_scheduler(glb_policy->base.combiner));
1401 grpc_call_error call_error = grpc_call_start_batch_and_execute(
1402 exec_ctx, glb_policy->lb_call, &op, 1,
1403 &glb_policy->client_load_report_closure);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001404 if (call_error != GRPC_CALL_OK) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001405 gpr_log(GPR_ERROR, "[grpclb %p] call_error=%d", glb_policy, call_error);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001406 GPR_ASSERT(GRPC_CALL_OK == call_error);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001407 }
1408}
1409
Craig Tillerbaa14a92017-11-03 09:09:36 -07001410static void lb_on_server_status_received_locked(grpc_exec_ctx* exec_ctx,
1411 void* arg, grpc_error* error);
1412static void lb_on_response_received_locked(grpc_exec_ctx* exec_ctx, void* arg,
1413 grpc_error* error);
1414static void lb_call_init_locked(grpc_exec_ctx* exec_ctx,
1415 glb_lb_policy* glb_policy) {
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001416 GPR_ASSERT(glb_policy->server_name != NULL);
1417 GPR_ASSERT(glb_policy->server_name[0] != '\0');
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001418 GPR_ASSERT(glb_policy->lb_call == NULL);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001419 GPR_ASSERT(!glb_policy->shutting_down);
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001420
David Garcia Quintas15eba132016-08-09 15:20:48 -07001421 /* Note the following LB call progresses every time there's activity in \a
1422 * glb_policy->base.interested_parties, which is comprised of the polling
Yuchen Zengf7c45ae2016-09-15 13:40:32 -07001423 * entities from \a client_channel. */
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001424 grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name);
Craig Tiller89c14282017-07-19 15:32:27 -07001425 grpc_millis deadline =
Mark D. Roth64d922a2017-05-03 12:52:04 -07001426 glb_policy->lb_call_timeout_ms == 0
Craig Tiller89c14282017-07-19 15:32:27 -07001427 ? GRPC_MILLIS_INF_FUTURE
1428 : grpc_exec_ctx_now(exec_ctx) + glb_policy->lb_call_timeout_ms;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001429 glb_policy->lb_call = grpc_channel_create_pollset_set_call(
Craig Tiller87a7e1f2016-11-09 09:42:19 -08001430 exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
David Garcia Quintas4543e5c2016-09-22 15:09:34 -07001431 glb_policy->base.interested_parties,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001432 GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
Mark D. Roth64d922a2017-05-03 12:52:04 -07001433 &host, deadline, NULL);
David Garcia Quintas7fadeae2017-04-18 14:38:56 -07001434 grpc_slice_unref_internal(exec_ctx, host);
David Garcia Quintas65318262016-07-29 13:43:38 -07001435
Mark D. Roth09e458c2017-05-02 08:13:26 -07001436 if (glb_policy->client_stats != NULL) {
1437 grpc_grpclb_client_stats_unref(glb_policy->client_stats);
1438 }
1439 glb_policy->client_stats = grpc_grpclb_client_stats_create();
1440
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001441 grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv);
1442 grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001443
Craig Tillerbaa14a92017-11-03 09:09:36 -07001444 grpc_grpclb_request* request =
David Garcia Quintas55ba14a2016-09-27 18:45:30 -07001445 grpc_grpclb_request_create(glb_policy->server_name);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001446 grpc_slice request_payload_slice = grpc_grpclb_request_encode(request);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001447 glb_policy->lb_request_payload =
David Garcia Quintas65318262016-07-29 13:43:38 -07001448 grpc_raw_byte_buffer_create(&request_payload_slice, 1);
Craig Tiller18b4ba32016-11-09 15:23:42 -08001449 grpc_slice_unref_internal(exec_ctx, request_payload_slice);
David Garcia Quintas65318262016-07-29 13:43:38 -07001450 grpc_grpclb_request_destroy(request);
1451
ncteisen969b46e2017-06-08 14:57:11 -07001452 GRPC_CLOSURE_INIT(&glb_policy->lb_on_server_status_received,
Craig Tiller2400bf52017-02-09 16:25:19 -08001453 lb_on_server_status_received_locked, glb_policy,
Craig Tilleree4b1452017-05-12 10:56:03 -07001454 grpc_combiner_scheduler(glb_policy->base.combiner));
ncteisen969b46e2017-06-08 14:57:11 -07001455 GRPC_CLOSURE_INIT(&glb_policy->lb_on_response_received,
Craig Tiller2400bf52017-02-09 16:25:19 -08001456 lb_on_response_received_locked, glb_policy,
Craig Tilleree4b1452017-05-12 10:56:03 -07001457 grpc_combiner_scheduler(glb_policy->base.combiner));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001458
Craig Tillerc0df1c02017-07-17 16:12:33 -07001459 grpc_backoff_init(&glb_policy->lb_call_backoff_state,
David Garcia Quintaseca25f32017-11-02 14:52:54 -07001460 GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
Craig Tillerc0df1c02017-07-17 16:12:33 -07001461 GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER,
1462 GRPC_GRPCLB_RECONNECT_JITTER,
1463 GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000,
1464 GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001465
Mark D. Roth09e458c2017-05-02 08:13:26 -07001466 glb_policy->seen_initial_response = false;
1467 glb_policy->last_client_load_report_counters_were_zero = false;
David Garcia Quintas65318262016-07-29 13:43:38 -07001468}
David Garcia Quintas8d489112016-07-29 15:20:42 -07001469
Craig Tillerbaa14a92017-11-03 09:09:36 -07001470static void lb_call_destroy_locked(grpc_exec_ctx* exec_ctx,
1471 glb_lb_policy* glb_policy) {
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001472 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tillerdd36b152017-03-31 08:27:28 -07001473 grpc_call_unref(glb_policy->lb_call);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001474 glb_policy->lb_call = NULL;
David Garcia Quintas65318262016-07-29 13:43:38 -07001475
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001476 grpc_metadata_array_destroy(&glb_policy->lb_initial_metadata_recv);
1477 grpc_metadata_array_destroy(&glb_policy->lb_trailing_metadata_recv);
David Garcia Quintas65318262016-07-29 13:43:38 -07001478
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001479 grpc_byte_buffer_destroy(glb_policy->lb_request_payload);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001480 grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001481
Mark D. Roth9247ad52017-09-25 13:35:48 -07001482 if (glb_policy->client_load_report_timer_pending) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001483 grpc_timer_cancel(exec_ctx, &glb_policy->client_load_report_timer);
1484 }
David Garcia Quintas65318262016-07-29 13:43:38 -07001485}
1486
David Garcia Quintas8d489112016-07-29 15:20:42 -07001487/*
1488 * Auxiliary functions and LB client callbacks.
1489 */
Craig Tillerbaa14a92017-11-03 09:09:36 -07001490static void query_for_backends_locked(grpc_exec_ctx* exec_ctx,
1491 glb_lb_policy* glb_policy) {
David Garcia Quintas65318262016-07-29 13:43:38 -07001492 GPR_ASSERT(glb_policy->lb_channel != NULL);
David Garcia Quintasa74b2462016-11-11 14:07:27 -08001493 if (glb_policy->shutting_down) return;
1494
Craig Tillerc5866662016-11-16 15:25:00 -08001495 lb_call_init_locked(exec_ctx, glb_policy);
David Garcia Quintas65318262016-07-29 13:43:38 -07001496
Craig Tiller84f75d42017-05-03 13:06:35 -07001497 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001498 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001499 "[grpclb %p] Query for backends (lb_channel: %p, lb_call: %p)",
1500 glb_policy, glb_policy->lb_channel, glb_policy->lb_call);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001501 }
1502 GPR_ASSERT(glb_policy->lb_call != NULL);
1503
David Garcia Quintas65318262016-07-29 13:43:38 -07001504 grpc_call_error call_error;
Mark D. Roth2de36a82017-09-25 14:54:44 -07001505 grpc_op ops[3];
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001506 memset(ops, 0, sizeof(ops));
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001507
Craig Tillerbaa14a92017-11-03 09:09:36 -07001508 grpc_op* op = ops;
David Garcia Quintas65318262016-07-29 13:43:38 -07001509 op->op = GRPC_OP_SEND_INITIAL_METADATA;
1510 op->data.send_initial_metadata.count = 0;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001511 op->flags = 0;
1512 op->reserved = NULL;
1513 op++;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001514 op->op = GRPC_OP_RECV_INITIAL_METADATA;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001515 op->data.recv_initial_metadata.recv_initial_metadata =
1516 &glb_policy->lb_initial_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001517 op->flags = 0;
1518 op->reserved = NULL;
1519 op++;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001520 GPR_ASSERT(glb_policy->lb_request_payload != NULL);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001521 op->op = GRPC_OP_SEND_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001522 op->data.send_message.send_message = glb_policy->lb_request_payload;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001523 op->flags = 0;
1524 op->reserved = NULL;
1525 op++;
Mark D. Roth2de36a82017-09-25 14:54:44 -07001526 call_error = grpc_call_start_batch_and_execute(exec_ctx, glb_policy->lb_call,
1527 ops, (size_t)(op - ops), NULL);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001528 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001529
Mark D. Roth09e458c2017-05-02 08:13:26 -07001530 op = ops;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001531 op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
1532 op->data.recv_status_on_client.trailing_metadata =
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001533 &glb_policy->lb_trailing_metadata_recv;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001534 op->data.recv_status_on_client.status = &glb_policy->lb_call_status;
1535 op->data.recv_status_on_client.status_details =
1536 &glb_policy->lb_call_status_details;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001537 op->flags = 0;
1538 op->reserved = NULL;
1539 op++;
David Garcia Quintase224a762016-11-01 13:00:58 -07001540 /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001541 * count goes to zero) to be unref'd in lb_on_server_status_received_locked */
1542 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base,
1543 "lb_on_server_status_received_locked");
David Garcia Quintas65318262016-07-29 13:43:38 -07001544 call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001545 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1546 &glb_policy->lb_on_server_status_received);
David Garcia Quintas65318262016-07-29 13:43:38 -07001547 GPR_ASSERT(GRPC_CALL_OK == call_error);
1548
1549 op = ops;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001550 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001551 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001552 op->flags = 0;
1553 op->reserved = NULL;
1554 op++;
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001555 /* take another weak ref to be unref'd/reused in
1556 * lb_on_response_received_locked */
1557 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_response_received_locked");
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001558 call_error = grpc_call_start_batch_and_execute(
1559 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1560 &glb_policy->lb_on_response_received);
David Garcia Quintas280fd2a2016-06-20 22:04:48 -07001561 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001562}
1563
Craig Tillerbaa14a92017-11-03 09:09:36 -07001564static void lb_on_response_received_locked(grpc_exec_ctx* exec_ctx, void* arg,
1565 grpc_error* error) {
1566 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001567 grpc_op ops[2];
1568 memset(ops, 0, sizeof(ops));
Craig Tillerbaa14a92017-11-03 09:09:36 -07001569 grpc_op* op = ops;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001570 if (glb_policy->lb_response_payload != NULL) {
Craig Tillerc0df1c02017-07-17 16:12:33 -07001571 grpc_backoff_reset(&glb_policy->lb_call_backoff_state);
David Garcia Quintas41bef452016-07-28 19:19:58 -07001572 /* Received data from the LB server. Look inside
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001573 * glb_policy->lb_response_payload, for a serverlist. */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001574 grpc_byte_buffer_reader bbr;
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001575 grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001576 grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr);
David Garcia Quintas97e17852017-08-14 14:55:02 -07001577 grpc_byte_buffer_reader_destroy(&bbr);
David Garcia Quintas7ec29132016-11-01 04:09:05 +01001578 grpc_byte_buffer_destroy(glb_policy->lb_response_payload);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001579
Craig Tillerbaa14a92017-11-03 09:09:36 -07001580 grpc_grpclb_initial_response* response = NULL;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001581 if (!glb_policy->seen_initial_response &&
1582 (response = grpc_grpclb_initial_response_parse(response_slice)) !=
1583 NULL) {
1584 if (response->has_client_stats_report_interval) {
Craig Tillerc0df1c02017-07-17 16:12:33 -07001585 glb_policy->client_stats_report_interval = GPR_MAX(
1586 GPR_MS_PER_SEC, grpc_grpclb_duration_to_millis(
1587 &response->client_stats_report_interval));
Craig Tiller84f75d42017-05-03 13:06:35 -07001588 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasea11d162016-07-14 17:27:28 -07001589 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001590 "[grpclb %p] Received initial LB response message; "
Craig Tillerc0df1c02017-07-17 16:12:33 -07001591 "client load reporting interval = %" PRIdPTR " milliseconds",
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001592 glb_policy, glb_policy->client_stats_report_interval);
David Garcia Quintasea11d162016-07-14 17:27:28 -07001593 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001594 /* take a weak ref (won't prevent calling of \a glb_shutdown() if the
1595 * strong ref count goes to zero) to be unref'd in
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001596 * send_client_load_report_locked() */
Mark D. Roth09e458c2017-05-02 08:13:26 -07001597 glb_policy->client_load_report_timer_pending = true;
1598 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "client_load_report");
1599 schedule_next_client_load_report(exec_ctx, glb_policy);
Craig Tiller84f75d42017-05-03 13:06:35 -07001600 } else if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001601 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001602 "[grpclb %p] Received initial LB response message; client load "
1603 "reporting NOT enabled",
1604 glb_policy);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001605 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001606 grpc_grpclb_initial_response_destroy(response);
1607 glb_policy->seen_initial_response = true;
1608 } else {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001609 grpc_grpclb_serverlist* serverlist =
Mark D. Roth09e458c2017-05-02 08:13:26 -07001610 grpc_grpclb_response_parse_serverlist(response_slice);
1611 if (serverlist != NULL) {
1612 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tiller84f75d42017-05-03 13:06:35 -07001613 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001614 gpr_log(GPR_INFO,
1615 "[grpclb %p] Serverlist with %" PRIuPTR " servers received",
1616 glb_policy, serverlist->num_servers);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001617 for (size_t i = 0; i < serverlist->num_servers; ++i) {
1618 grpc_resolved_address addr;
1619 parse_server(serverlist->servers[i], &addr);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001620 char* ipport;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001621 grpc_sockaddr_to_string(&ipport, &addr, false);
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001622 gpr_log(GPR_INFO, "[grpclb %p] Serverlist[%" PRIuPTR "]: %s",
1623 glb_policy, i, ipport);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001624 gpr_free(ipport);
1625 }
1626 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001627 /* update serverlist */
1628 if (serverlist->num_servers > 0) {
1629 if (grpc_grpclb_serverlist_equals(glb_policy->serverlist,
1630 serverlist)) {
Craig Tiller84f75d42017-05-03 13:06:35 -07001631 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
Mark D. Roth09e458c2017-05-02 08:13:26 -07001632 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001633 "[grpclb %p] Incoming server list identical to current, "
1634 "ignoring.",
1635 glb_policy);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001636 }
1637 grpc_grpclb_destroy_serverlist(serverlist);
1638 } else { /* new serverlist */
1639 if (glb_policy->serverlist != NULL) {
1640 /* dispose of the old serverlist */
1641 grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
Juanli Shenfe408152017-09-27 12:27:20 -07001642 } else {
1643 /* or dispose of the fallback */
1644 grpc_lb_addresses_destroy(exec_ctx,
1645 glb_policy->fallback_backend_addresses);
1646 glb_policy->fallback_backend_addresses = NULL;
1647 if (glb_policy->fallback_timer_active) {
1648 grpc_timer_cancel(exec_ctx, &glb_policy->lb_fallback_timer);
1649 glb_policy->fallback_timer_active = false;
1650 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001651 }
1652 /* and update the copy in the glb_lb_policy instance. This
1653 * serverlist instance will be destroyed either upon the next
1654 * update or in glb_destroy() */
1655 glb_policy->serverlist = serverlist;
Mark D. Rothd7389b42017-05-17 12:22:17 -07001656 glb_policy->serverlist_index = 0;
Mark D. Roth09e458c2017-05-02 08:13:26 -07001657 rr_handover_locked(exec_ctx, glb_policy);
1658 }
1659 } else {
Craig Tiller84f75d42017-05-03 13:06:35 -07001660 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001661 gpr_log(GPR_INFO,
1662 "[grpclb %p] Received empty server list, ignoring.",
1663 glb_policy);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001664 }
1665 grpc_grpclb_destroy_serverlist(serverlist);
1666 }
1667 } else { /* serverlist == NULL */
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001668 gpr_log(GPR_ERROR,
1669 "[grpclb %p] Invalid LB response received: '%s'. Ignoring.",
1670 glb_policy,
Mark D. Roth09e458c2017-05-02 08:13:26 -07001671 grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX));
1672 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001673 }
Mark D. Roth09e458c2017-05-02 08:13:26 -07001674 grpc_slice_unref_internal(exec_ctx, response_slice);
David Garcia Quintas246c5642016-11-01 11:16:52 -07001675 if (!glb_policy->shutting_down) {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001676 /* keep listening for serverlist updates */
1677 op->op = GRPC_OP_RECV_MESSAGE;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001678 op->data.recv_message.recv_message = &glb_policy->lb_response_payload;
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001679 op->flags = 0;
1680 op->reserved = NULL;
1681 op++;
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001682 /* reuse the "lb_on_response_received_locked" weak ref taken in
David Garcia Quintase224a762016-11-01 13:00:58 -07001683 * query_for_backends_locked() */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001684 const grpc_call_error call_error = grpc_call_start_batch_and_execute(
David Garcia Quintas246c5642016-11-01 11:16:52 -07001685 exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops),
1686 &glb_policy->lb_on_response_received); /* loop */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001687 GPR_ASSERT(GRPC_CALL_OK == call_error);
David Garcia Quintas998bd2c2017-09-18 12:41:07 -07001688 } else {
1689 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1690 "lb_on_response_received_locked_shutdown");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001691 }
David Garcia Quintase224a762016-11-01 13:00:58 -07001692 } else { /* empty payload: call cancelled. */
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001693 /* dispose of the "lb_on_response_received_locked" weak ref taken in
David Garcia Quintase224a762016-11-01 13:00:58 -07001694 * query_for_backends_locked() and reused in every reception loop */
1695 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
David Garcia Quintasc22c65b2017-07-25 14:22:20 -07001696 "lb_on_response_received_locked_empty_payload");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001697 }
1698}
David Garcia Quintasea11d162016-07-14 17:27:28 -07001699
Craig Tillerbaa14a92017-11-03 09:09:36 -07001700static void lb_on_fallback_timer_locked(grpc_exec_ctx* exec_ctx, void* arg,
1701 grpc_error* error) {
1702 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
Juanli Shenfe408152017-09-27 12:27:20 -07001703 glb_policy->fallback_timer_active = false;
1704 /* If we receive a serverlist after the timer fires but before this callback
1705 * actually runs, don't fall back. */
1706 if (glb_policy->serverlist == NULL) {
1707 if (!glb_policy->shutting_down && error == GRPC_ERROR_NONE) {
1708 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
1709 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001710 "[grpclb %p] Falling back to use backends from resolver",
1711 glb_policy);
Juanli Shenfe408152017-09-27 12:27:20 -07001712 }
1713 GPR_ASSERT(glb_policy->fallback_backend_addresses != NULL);
1714 rr_handover_locked(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001715 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001716 }
Juanli Shenfe408152017-09-27 12:27:20 -07001717 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1718 "grpclb_fallback_timer");
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001719}
1720
Craig Tillerbaa14a92017-11-03 09:09:36 -07001721static void lb_on_server_status_received_locked(grpc_exec_ctx* exec_ctx,
1722 void* arg, grpc_error* error) {
1723 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001724 GPR_ASSERT(glb_policy->lb_call != NULL);
Craig Tiller84f75d42017-05-03 13:06:35 -07001725 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001726 char* status_details =
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001727 grpc_slice_to_c_string(glb_policy->lb_call_status_details);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001728 gpr_log(GPR_INFO,
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001729 "[grpclb %p] Status from LB server received. Status = %d, Details "
1730 "= '%s', "
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001731 "(call: %p), error %p",
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001732 glb_policy, glb_policy->lb_call_status, status_details,
1733 glb_policy->lb_call, error);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001734 gpr_free(status_details);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001735 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001736 /* We need to perform cleanups no matter what. */
1737 lb_call_destroy_locked(exec_ctx, glb_policy);
Mark D. Rotha4792f52017-09-26 09:06:35 -07001738 // If the load report timer is still pending, we wait for it to be
1739 // called before restarting the call. Otherwise, we restart the call
1740 // here.
1741 if (!glb_policy->client_load_report_timer_pending) {
1742 maybe_restart_lb_call(exec_ctx, glb_policy);
David Garcia Quintas98da61b2016-10-29 08:46:31 +02001743 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001744}
1745
Craig Tillerbaa14a92017-11-03 09:09:36 -07001746static void fallback_update_locked(grpc_exec_ctx* exec_ctx,
1747 glb_lb_policy* glb_policy,
1748 const grpc_lb_addresses* addresses) {
Juanli Shenfe408152017-09-27 12:27:20 -07001749 GPR_ASSERT(glb_policy->fallback_backend_addresses != NULL);
1750 grpc_lb_addresses_destroy(exec_ctx, glb_policy->fallback_backend_addresses);
1751 glb_policy->fallback_backend_addresses =
1752 extract_backend_addresses_locked(exec_ctx, addresses);
1753 if (glb_policy->lb_fallback_timeout_ms > 0 &&
1754 !glb_policy->fallback_timer_active) {
1755 rr_handover_locked(exec_ctx, glb_policy);
1756 }
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001757}
1758
Craig Tillerbaa14a92017-11-03 09:09:36 -07001759static void glb_update_locked(grpc_exec_ctx* exec_ctx, grpc_lb_policy* policy,
1760 const grpc_lb_policy_args* args) {
1761 glb_lb_policy* glb_policy = (glb_lb_policy*)policy;
1762 const grpc_arg* arg =
Juanli Shenfe408152017-09-27 12:27:20 -07001763 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
1764 if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
1765 if (glb_policy->lb_channel == NULL) {
1766 // If we don't have a current channel to the LB, go into TRANSIENT
1767 // FAILURE.
1768 grpc_connectivity_state_set(
1769 exec_ctx, &glb_policy->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
1770 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"),
1771 "glb_update_missing");
1772 } else {
1773 // otherwise, keep using the current LB channel (ignore this update).
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001774 gpr_log(
1775 GPR_ERROR,
1776 "[grpclb %p] No valid LB addresses channel arg in update, ignoring.",
1777 glb_policy);
Juanli Shenfe408152017-09-27 12:27:20 -07001778 }
1779 return;
1780 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001781 const grpc_lb_addresses* addresses =
1782 (const grpc_lb_addresses*)arg->value.pointer.p;
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001783 // If a non-empty serverlist hasn't been received from the balancer,
1784 // propagate the update to fallback_backend_addresses.
Juanli Shenfe408152017-09-27 12:27:20 -07001785 if (glb_policy->serverlist == NULL) {
Juanli Shenfe408152017-09-27 12:27:20 -07001786 fallback_update_locked(exec_ctx, glb_policy, addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001787 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001788 GPR_ASSERT(glb_policy->lb_channel != NULL);
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001789 // Propagate updates to the LB channel (pick_first) through the fake
1790 // resolver.
Craig Tillerbaa14a92017-11-03 09:09:36 -07001791 grpc_channel_args* lb_channel_args = build_lb_channel_args(
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001792 exec_ctx, addresses, glb_policy->response_generator, args->args);
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001793 grpc_fake_resolver_response_generator_set_response(
1794 exec_ctx, glb_policy->response_generator, lb_channel_args);
1795 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001796 // Start watching the LB channel connectivity for connection, if not
1797 // already doing so.
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001798 if (!glb_policy->watching_lb_channel) {
David Garcia Quintas6a7935e2017-07-27 19:24:52 -07001799 glb_policy->lb_channel_connectivity = grpc_channel_check_connectivity_state(
1800 glb_policy->lb_channel, true /* try to connect */);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001801 grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element(
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001802 grpc_channel_get_channel_stack(glb_policy->lb_channel));
1803 GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1804 glb_policy->watching_lb_channel = true;
1805 GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "watch_lb_channel_connectivity");
1806 grpc_client_channel_watch_connectivity_state(
1807 exec_ctx, client_channel_elem,
1808 grpc_polling_entity_create_from_pollset_set(
1809 glb_policy->base.interested_parties),
1810 &glb_policy->lb_channel_connectivity,
1811 &glb_policy->lb_channel_on_connectivity_changed, NULL);
1812 }
1813}
1814
1815// Invoked as part of the update process. It continues watching the LB channel
1816// until it shuts down or becomes READY. It's invoked even if the LB channel
1817// stayed READY throughout the update (for example if the update is identical).
Craig Tillerbaa14a92017-11-03 09:09:36 -07001818static void glb_lb_channel_on_connectivity_changed_cb(grpc_exec_ctx* exec_ctx,
1819 void* arg,
1820 grpc_error* error) {
1821 glb_lb_policy* glb_policy = (glb_lb_policy*)arg;
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001822 if (glb_policy->shutting_down) goto done;
1823 // Re-initialize the lb_call. This should also take care of updating the
1824 // embedded RR policy. Note that the current RR policy, if any, will stay in
1825 // effect until an update from the new lb_call is received.
1826 switch (glb_policy->lb_channel_connectivity) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001827 case GRPC_CHANNEL_CONNECTING:
1828 case GRPC_CHANNEL_TRANSIENT_FAILURE: {
1829 /* resub. */
Craig Tillerbaa14a92017-11-03 09:09:36 -07001830 grpc_channel_element* client_channel_elem =
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001831 grpc_channel_stack_last_element(
1832 grpc_channel_get_channel_stack(glb_policy->lb_channel));
1833 GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter);
1834 grpc_client_channel_watch_connectivity_state(
1835 exec_ctx, client_channel_elem,
1836 grpc_polling_entity_create_from_pollset_set(
1837 glb_policy->base.interested_parties),
1838 &glb_policy->lb_channel_connectivity,
1839 &glb_policy->lb_channel_on_connectivity_changed, NULL);
1840 break;
1841 }
1842 case GRPC_CHANNEL_IDLE:
David Garcia Quintas2b217d42017-10-20 15:56:30 -07001843 // lb channel inactive (probably shutdown prior to update). Restart lb
1844 // call to kick the lb channel into gear.
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001845 /* fallthrough */
1846 case GRPC_CHANNEL_READY:
1847 if (glb_policy->lb_call != NULL) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001848 glb_policy->updating_lb_call = true;
1849 grpc_call_cancel(glb_policy->lb_call, NULL);
Mark D. Roth97b6e5d2017-10-09 08:31:41 -07001850 // lb_on_server_status_received() will pick up the cancel and reinit
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001851 // lb_call.
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001852 } else if (glb_policy->started_picking && !glb_policy->shutting_down) {
1853 if (glb_policy->retry_timer_active) {
1854 grpc_timer_cancel(exec_ctx, &glb_policy->lb_call_retry_timer);
1855 glb_policy->retry_timer_active = false;
1856 }
1857 start_picking_locked(exec_ctx, glb_policy);
1858 }
1859 /* fallthrough */
1860 case GRPC_CHANNEL_SHUTDOWN:
1861 done:
1862 glb_policy->watching_lb_channel = false;
1863 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
1864 "watch_lb_channel_connectivity_cb_shutdown");
1865 break;
1866 }
1867}
1868
David Garcia Quintas8d489112016-07-29 15:20:42 -07001869/* Code wiring the policy with the rest of the core */
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001870static const grpc_lb_policy_vtable glb_lb_policy_vtable = {
Craig Tiller2400bf52017-02-09 16:25:19 -08001871 glb_destroy,
1872 glb_shutdown_locked,
1873 glb_pick_locked,
1874 glb_cancel_pick_locked,
1875 glb_cancel_picks_locked,
1876 glb_ping_one_locked,
1877 glb_exit_idle_locked,
1878 glb_check_connectivity_locked,
David Garcia Quintas87d5a312017-06-06 19:45:58 -07001879 glb_notify_on_state_change_locked,
1880 glb_update_locked};
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001881
Craig Tillerbaa14a92017-11-03 09:09:36 -07001882static grpc_lb_policy* glb_create(grpc_exec_ctx* exec_ctx,
1883 grpc_lb_policy_factory* factory,
1884 grpc_lb_policy_args* args) {
Juanli Shenfe408152017-09-27 12:27:20 -07001885 /* Count the number of gRPC-LB addresses. There must be at least one. */
Craig Tillerbaa14a92017-11-03 09:09:36 -07001886 const grpc_arg* arg =
Yash Tibrewala4952202017-09-13 10:53:28 -07001887 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
1888 if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
1889 return NULL;
1890 }
Craig Tillerbaa14a92017-11-03 09:09:36 -07001891 grpc_lb_addresses* addresses = (grpc_lb_addresses*)arg->value.pointer.p;
Yash Tibrewala4952202017-09-13 10:53:28 -07001892 size_t num_grpclb_addrs = 0;
1893 for (size_t i = 0; i < addresses->num_addresses; ++i) {
1894 if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
1895 }
1896 if (num_grpclb_addrs == 0) return NULL;
1897
Craig Tillerbaa14a92017-11-03 09:09:36 -07001898 glb_lb_policy* glb_policy = (glb_lb_policy*)gpr_zalloc(sizeof(*glb_policy));
Yash Tibrewala4952202017-09-13 10:53:28 -07001899
1900 /* Get server name. */
1901 arg = grpc_channel_args_find(args->args, GRPC_ARG_SERVER_URI);
1902 GPR_ASSERT(arg != NULL);
1903 GPR_ASSERT(arg->type == GRPC_ARG_STRING);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001904 grpc_uri* uri = grpc_uri_parse(exec_ctx, arg->value.string, true);
Yash Tibrewala4952202017-09-13 10:53:28 -07001905 GPR_ASSERT(uri->path[0] != '\0');
1906 glb_policy->server_name =
1907 gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path);
1908 if (GRPC_TRACER_ON(grpc_lb_glb_trace)) {
David Garcia Quintasa1c65902017-11-09 10:37:35 -08001909 gpr_log(GPR_INFO,
1910 "[grpclb %p] Will use '%s' as the server name for LB request.",
1911 glb_policy, glb_policy->server_name);
Yash Tibrewala4952202017-09-13 10:53:28 -07001912 }
1913 grpc_uri_destroy(uri);
1914
1915 glb_policy->cc_factory = args->client_channel_factory;
1916 GPR_ASSERT(glb_policy->cc_factory != NULL);
1917
1918 arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS);
1919 glb_policy->lb_call_timeout_ms =
Yash Tibrewald8b84a22017-09-25 13:38:03 -07001920 grpc_channel_arg_get_integer(arg, {0, 0, INT_MAX});
Yash Tibrewala4952202017-09-13 10:53:28 -07001921
Juanli Shenfe408152017-09-27 12:27:20 -07001922 arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS);
1923 glb_policy->lb_fallback_timeout_ms = grpc_channel_arg_get_integer(
Yash Tibrewal1150bfb2017-09-28 14:43:41 -07001924 arg, {GRPC_GRPCLB_DEFAULT_FALLBACK_TIMEOUT_MS, 0, INT_MAX});
Juanli Shenfe408152017-09-27 12:27:20 -07001925
Yash Tibrewala4952202017-09-13 10:53:28 -07001926 // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args,
1927 // since we use this to trigger the client_load_reporting filter.
Yash Tibrewal9eb86722017-09-17 23:43:30 -07001928 grpc_arg new_arg = grpc_channel_arg_string_create(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001929 (char*)GRPC_ARG_LB_POLICY_NAME, (char*)"grpclb");
1930 static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME};
Yash Tibrewala4952202017-09-13 10:53:28 -07001931 glb_policy->args = grpc_channel_args_copy_and_add_and_remove(
1932 args->args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
1933
Juanli Shenfe408152017-09-27 12:27:20 -07001934 /* Extract the backend addresses (may be empty) from the resolver for
1935 * fallback. */
1936 glb_policy->fallback_backend_addresses =
1937 extract_backend_addresses_locked(exec_ctx, addresses);
1938
Yash Tibrewala4952202017-09-13 10:53:28 -07001939 /* Create a client channel over them to communicate with a LB service */
1940 glb_policy->response_generator =
1941 grpc_fake_resolver_response_generator_create();
Craig Tillerbaa14a92017-11-03 09:09:36 -07001942 grpc_channel_args* lb_channel_args = build_lb_channel_args(
Yash Tibrewala4952202017-09-13 10:53:28 -07001943 exec_ctx, addresses, glb_policy->response_generator, args->args);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001944 char* uri_str;
Yash Tibrewala4952202017-09-13 10:53:28 -07001945 gpr_asprintf(&uri_str, "fake:///%s", glb_policy->server_name);
1946 glb_policy->lb_channel = grpc_lb_policy_grpclb_create_lb_channel(
1947 exec_ctx, uri_str, args->client_channel_factory, lb_channel_args);
1948
1949 /* Propagate initial resolution */
1950 grpc_fake_resolver_response_generator_set_response(
1951 exec_ctx, glb_policy->response_generator, lb_channel_args);
1952 grpc_channel_args_destroy(exec_ctx, lb_channel_args);
1953 gpr_free(uri_str);
1954 if (glb_policy->lb_channel == NULL) {
Craig Tillerbaa14a92017-11-03 09:09:36 -07001955 gpr_free((void*)glb_policy->server_name);
Yash Tibrewala4952202017-09-13 10:53:28 -07001956 grpc_channel_args_destroy(exec_ctx, glb_policy->args);
1957 gpr_free(glb_policy);
1958 return NULL;
1959 }
Ken Payson9fa10cc2017-09-14 11:49:52 -07001960 grpc_subchannel_index_ref();
Yash Tibrewala4952202017-09-13 10:53:28 -07001961 GRPC_CLOSURE_INIT(&glb_policy->lb_channel_on_connectivity_changed,
1962 glb_lb_channel_on_connectivity_changed_cb, glb_policy,
1963 grpc_combiner_scheduler(args->combiner));
1964 grpc_lb_policy_init(&glb_policy->base, &glb_lb_policy_vtable, args->combiner);
1965 grpc_connectivity_state_init(&glb_policy->state_tracker, GRPC_CHANNEL_IDLE,
1966 "grpclb");
1967 return &glb_policy->base;
1968}
1969
Craig Tillerbaa14a92017-11-03 09:09:36 -07001970static void glb_factory_ref(grpc_lb_policy_factory* factory) {}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001971
Craig Tillerbaa14a92017-11-03 09:09:36 -07001972static void glb_factory_unref(grpc_lb_policy_factory* factory) {}
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001973
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001974static const grpc_lb_policy_factory_vtable glb_factory_vtable = {
1975 glb_factory_ref, glb_factory_unref, glb_create, "grpclb"};
1976
1977static grpc_lb_policy_factory glb_lb_policy_factory = {&glb_factory_vtable};
1978
Craig Tillerbaa14a92017-11-03 09:09:36 -07001979grpc_lb_policy_factory* grpc_glb_lb_factory_create() {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07001980 return &glb_lb_policy_factory;
1981}
1982
1983/* Plugin registration */
Mark D. Roth09e458c2017-05-02 08:13:26 -07001984
1985// Only add client_load_reporting filter if the grpclb LB policy is used.
1986static bool maybe_add_client_load_reporting_filter(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001987 grpc_exec_ctx* exec_ctx, grpc_channel_stack_builder* builder, void* arg) {
1988 const grpc_channel_args* args =
Mark D. Roth09e458c2017-05-02 08:13:26 -07001989 grpc_channel_stack_builder_get_channel_arguments(builder);
Craig Tillerbaa14a92017-11-03 09:09:36 -07001990 const grpc_arg* channel_arg =
Mark D. Roth09e458c2017-05-02 08:13:26 -07001991 grpc_channel_args_find(args, GRPC_ARG_LB_POLICY_NAME);
1992 if (channel_arg != NULL && channel_arg->type == GRPC_ARG_STRING &&
1993 strcmp(channel_arg->value.string, "grpclb") == 0) {
1994 return grpc_channel_stack_builder_append_filter(
Craig Tillerbaa14a92017-11-03 09:09:36 -07001995 builder, (const grpc_channel_filter*)arg, NULL, NULL);
Mark D. Roth09e458c2017-05-02 08:13:26 -07001996 }
1997 return true;
1998}
1999
Yash Tibrewal83062842017-09-21 18:56:08 -07002000extern "C" void grpc_lb_policy_grpclb_init() {
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07002001 grpc_register_lb_policy(grpc_glb_lb_factory_create());
ncteisen06bce6e2017-07-10 07:58:49 -07002002 grpc_register_tracer(&grpc_lb_glb_trace);
ncteisen4b584052017-06-08 16:44:38 -07002003#ifndef NDEBUG
ncteisen06bce6e2017-07-10 07:58:49 -07002004 grpc_register_tracer(&grpc_trace_lb_policy_refcount);
ncteisen4b584052017-06-08 16:44:38 -07002005#endif
Mark D. Roth09e458c2017-05-02 08:13:26 -07002006 grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
2007 GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
2008 maybe_add_client_load_reporting_filter,
Craig Tillerbaa14a92017-11-03 09:09:36 -07002009 (void*)&grpc_client_load_reporting_filter);
David Garcia Quintas3fb8f732016-06-15 22:53:08 -07002010}
2011
Yash Tibrewal83062842017-09-21 18:56:08 -07002012extern "C" void grpc_lb_policy_grpclb_shutdown() {}