blob: e4d7527ce8d11270838f5b202d59c2673429260e [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tillerd4c98332016-03-31 13:45:47 -070034#include "src/core/ext/client_config/client_channel.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
Mark D. Roth4c0fe492016-08-31 13:51:55 -070036#include <stdbool.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080037#include <stdio.h>
Craig Tillereb3b12e2015-06-26 14:42:49 -070038#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080040#include <grpc/support/alloc.h>
41#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080042#include <grpc/support/sync.h>
43#include <grpc/support/useful.h>
44
Mark D. Roth4c0fe492016-08-31 13:51:55 -070045#include "src/core/ext/client_config/subchannel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070046#include "src/core/lib/channel/channel_args.h"
47#include "src/core/lib/channel/connected_channel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070048#include "src/core/lib/iomgr/iomgr.h"
Mark D. Roth4c0fe492016-08-31 13:51:55 -070049#include "src/core/lib/iomgr/polling_entity.h"
Craig Tiller9533d042016-03-25 17:11:06 -070050#include "src/core/lib/profiling/timers.h"
51#include "src/core/lib/support/string.h"
52#include "src/core/lib/surface/channel.h"
53#include "src/core/lib/transport/connectivity_state.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070054
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055/* Client channel implementation */
56
Mark D. Roth4c0fe492016-08-31 13:51:55 -070057#define GET_CALL(call_data) \
58 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
59
60#define CANCELLED_CALL ((grpc_subchannel_call *)1)
61
62/** Picks a subchannel.
63 Returns true if subchannel is available immediately (in which case on_ready
64 should not be called), or false otherwise (in which case on_ready should be
65 called when the subchannel is available) */
66typedef bool (*pick_subchannel_cb)(
67 grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata,
68 uint32_t initial_metadata_flags,
69 grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready);
70
71typedef enum {
72 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
73 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
74} subchannel_creation_phase;
75
76/** Call data. Holds a pointer to grpc_subchannel_call and the
77 associated machinery to create such a pointer.
78 Handles queueing of stream ops until a call object is ready, waiting
79 for initial metadata before trying to create a call object,
80 and handling cancellation gracefully. */
81typedef struct client_channel_call_data {
82 /** either 0 for no call, 1 for cancelled, or a pointer to a
83 grpc_subchannel_call */
84 gpr_atm subchannel_call;
85 /** Helper function to choose the subchannel on which to create
86 the call object. Channel filter delegates to the load
87 balancing policy (once it's ready). */
88 pick_subchannel_cb pick_subchannel;
89 void *pick_subchannel_arg;
90
91 gpr_mu mu;
92
93 subchannel_creation_phase creation_phase;
94 grpc_connected_subchannel *connected_subchannel;
95 grpc_polling_entity *pollent;
96
97 grpc_transport_stream_op *waiting_ops;
98 size_t waiting_ops_count;
99 size_t waiting_ops_capacity;
100
101 grpc_closure next_step;
102
103 grpc_call_stack *owning_call;
104} call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800105
Craig Tiller800dacb2015-10-06 09:10:26 -0700106typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700107 /** resolver for this channel */
108 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700109 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700110 bool started_resolving;
Craig Tillerf5f17122015-06-25 08:47:26 -0700111
Craig Tiller9d94b602015-07-01 14:23:18 -0700112 /** mutex protecting client configuration, including all
113 variables below in this data structure */
Mark D. Rothff4df062016-08-22 15:02:49 -0700114 gpr_mu mu;
115 /** currently active load balancer - guarded by mu */
Craig Tillerf5f17122015-06-25 08:47:26 -0700116 grpc_lb_policy *lb_policy;
Mark D. Rothff4df062016-08-22 15:02:49 -0700117 /** incoming resolver result - set by resolver.next(), guarded by mu */
118 grpc_resolver_result *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700119 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700120 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700121 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700122 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700123 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700124 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700125 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700126 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800127 /** owning stack */
128 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800129 /** interested parties (owned) */
130 grpc_pollset_set *interested_parties;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800131} channel_data;
132
Craig Tillerd6c98df2015-08-18 09:33:44 -0700133/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700134 resolver, to watch for state changes from the lb_policy. When a state
135 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700136typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700137 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700138 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700139 grpc_connectivity_state state;
140 grpc_lb_policy *lb_policy;
141} lb_policy_connectivity_watcher;
142
Craig Tillera82950e2015-09-22 12:33:20 -0700143typedef struct {
Craig Tiller33825112015-09-18 07:44:19 -0700144 grpc_closure closure;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700145 grpc_call_element *elem;
146} waiting_call;
147
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700148static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
149 GPR_TIMER_BEGIN("add_waiting_locked", 0);
150 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
151 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
152 calld->waiting_ops =
153 gpr_realloc(calld->waiting_ops,
154 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
155 }
156 calld->waiting_ops[calld->waiting_ops_count++] = *op;
157 GPR_TIMER_END("add_waiting_locked", 0);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700158}
Craig Tillerf5f17122015-06-25 08:47:26 -0700159
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700160static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
161 grpc_error *error) {
162 size_t i;
163 for (i = 0; i < calld->waiting_ops_count; i++) {
164 grpc_transport_stream_op_finish_with_failure(
165 exec_ctx, &calld->waiting_ops[i], GRPC_ERROR_REF(error));
166 }
167 calld->waiting_ops_count = 0;
168 GRPC_ERROR_UNREF(error);
169}
170
171typedef struct {
172 grpc_transport_stream_op *ops;
173 size_t nops;
174 grpc_subchannel_call *call;
175} retry_ops_args;
176
177static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
178 retry_ops_args *a = args;
179 size_t i;
180 for (i = 0; i < a->nops; i++) {
181 grpc_subchannel_call_process_op(exec_ctx, a->call, &a->ops[i]);
182 }
183 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
184 gpr_free(a->ops);
185 gpr_free(a);
186}
187
188static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
189 retry_ops_args *a = gpr_malloc(sizeof(*a));
190 a->ops = calld->waiting_ops;
191 a->nops = calld->waiting_ops_count;
192 a->call = GET_CALL(calld);
193 if (a->call == CANCELLED_CALL) {
194 gpr_free(a);
195 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
196 return;
197 }
198 calld->waiting_ops = NULL;
199 calld->waiting_ops_count = 0;
200 calld->waiting_ops_capacity = 0;
201 GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
202 grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(retry_ops, a),
203 GRPC_ERROR_NONE, NULL);
204}
205
206static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
207 grpc_error *error) {
208 call_data *calld = arg;
209 gpr_mu_lock(&calld->mu);
210 GPR_ASSERT(calld->creation_phase ==
211 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
212 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
213 if (calld->connected_subchannel == NULL) {
214 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
215 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
216 "Failed to create subchannel", &error, 1));
217 } else if (1 == gpr_atm_acq_load(&calld->subchannel_call)) {
218 /* already cancelled before subchannel became ready */
219 fail_locked(exec_ctx, calld,
220 GRPC_ERROR_CREATE_REFERENCING(
221 "Cancelled before creating subchannel", &error, 1));
222 } else {
223 grpc_subchannel_call *subchannel_call = NULL;
224 grpc_error *new_error = grpc_connected_subchannel_create_call(
225 exec_ctx, calld->connected_subchannel, calld->pollent,
226 &subchannel_call);
227 if (new_error != GRPC_ERROR_NONE) {
228 new_error = grpc_error_add_child(new_error, error);
229 subchannel_call = CANCELLED_CALL;
230 fail_locked(exec_ctx, calld, new_error);
231 }
232 gpr_atm_rel_store(&calld->subchannel_call,
233 (gpr_atm)(uintptr_t)subchannel_call);
234 retry_waiting_locked(exec_ctx, calld);
235 }
236 gpr_mu_unlock(&calld->mu);
237 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
238}
239
240static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
241 call_data *calld = elem->call_data;
242 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
243 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
244 return NULL;
245 } else {
246 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
247 }
248}
249
250// The logic here is fairly complicated, due to (a) the fact that we
251// need to handle the case where we receive the send op before the
252// initial metadata op, and (b) the need for efficiency, especially in
253// the streaming case.
254// TODO(ctiller): Explain this more thoroughly.
Craig Tillera82950e2015-09-22 12:33:20 -0700255static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
256 grpc_call_element *elem,
257 grpc_transport_stream_op *op) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700258 call_data *calld = elem->call_data;
Craig Tiller577c9b22015-11-02 14:11:15 -0800259 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700260 /* try to (atomically) get the call */
261 grpc_subchannel_call *call = GET_CALL(calld);
262 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
263 if (call == CANCELLED_CALL) {
264 grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
265 GRPC_ERROR_CANCELLED);
266 GPR_TIMER_END("cc_start_transport_stream_op", 0);
267 return;
268 }
269 if (call != NULL) {
270 grpc_subchannel_call_process_op(exec_ctx, call, op);
271 GPR_TIMER_END("cc_start_transport_stream_op", 0);
272 return;
273 }
274 /* we failed; lock and figure out what to do */
275 gpr_mu_lock(&calld->mu);
276retry:
277 /* need to recheck that another thread hasn't set the call */
278 call = GET_CALL(calld);
279 if (call == CANCELLED_CALL) {
280 gpr_mu_unlock(&calld->mu);
281 grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
282 GRPC_ERROR_CANCELLED);
283 GPR_TIMER_END("cc_start_transport_stream_op", 0);
284 return;
285 }
286 if (call != NULL) {
287 gpr_mu_unlock(&calld->mu);
288 grpc_subchannel_call_process_op(exec_ctx, call, op);
289 GPR_TIMER_END("cc_start_transport_stream_op", 0);
290 return;
291 }
292 /* if this is a cancellation, then we can raise our cancelled flag */
293 if (op->cancel_error != GRPC_ERROR_NONE) {
294 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
295 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
296 goto retry;
297 } else {
298 switch (calld->creation_phase) {
299 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
300 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
301 break;
302 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
303 calld->pick_subchannel(exec_ctx, calld->pick_subchannel_arg, NULL, 0,
304 &calld->connected_subchannel, NULL);
305 break;
306 }
307 gpr_mu_unlock(&calld->mu);
308 grpc_transport_stream_op_finish_with_failure(exec_ctx, op,
309 GRPC_ERROR_CANCELLED);
310 GPR_TIMER_END("cc_start_transport_stream_op", 0);
311 return;
312 }
313 }
314 /* if we don't have a subchannel, try to get one */
315 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
316 calld->connected_subchannel == NULL &&
317 op->send_initial_metadata != NULL) {
318 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
319 grpc_closure_init(&calld->next_step, subchannel_ready, calld);
320 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
321 if (calld->pick_subchannel(
322 exec_ctx, calld->pick_subchannel_arg, op->send_initial_metadata,
323 op->send_initial_metadata_flags, &calld->connected_subchannel,
324 &calld->next_step)) {
325 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
326 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
327 }
328 }
329 /* if we've got a subchannel, then let's ask it to create a call */
330 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
331 calld->connected_subchannel != NULL) {
332 grpc_subchannel_call *subchannel_call = NULL;
333 grpc_error *error = grpc_connected_subchannel_create_call(
334 exec_ctx, calld->connected_subchannel, calld->pollent,
335 &subchannel_call);
336 if (error != GRPC_ERROR_NONE) {
337 subchannel_call = CANCELLED_CALL;
338 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
339 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
340 }
341 gpr_atm_rel_store(&calld->subchannel_call,
342 (gpr_atm)(uintptr_t)subchannel_call);
343 retry_waiting_locked(exec_ctx, calld);
344 goto retry;
345 }
346 /* nothing to be done but wait */
347 add_waiting_locked(calld, op);
348 gpr_mu_unlock(&calld->mu);
349 GPR_TIMER_END("cc_start_transport_stream_op", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800350}
351
Craig Tillera82950e2015-09-22 12:33:20 -0700352static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
353 grpc_lb_policy *lb_policy,
354 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700355
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800356static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
357 channel_data *chand,
358 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700359 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800360 const char *reason) {
361 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700362 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800363 chand->lb_policy != NULL) {
364 /* cancel fail-fast picks */
365 grpc_lb_policy_cancel_picks(
366 exec_ctx, chand->lb_policy,
367 /* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY,
368 /* check= */ 0);
369 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700370 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
371 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800372}
373
Craig Tiller804ff712016-05-05 16:25:40 -0700374static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
375 lb_policy_connectivity_watcher *w,
376 grpc_error *error) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800377 grpc_connectivity_state publish_state = w->state;
Craig Tiller5795da72015-09-17 15:27:13 -0700378 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700379 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700380
Craig Tiller48ed92e2016-06-02 11:07:12 -0700381 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800382 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
383 grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
Craig Tillerf62c4d52015-12-04 07:43:07 -0800384 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
385 w->chand->lb_policy = NULL;
Craig Tillercb2609f2015-11-24 17:19:19 -0800386 }
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800387 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
Craig Tillerfc353d62016-05-10 12:58:03 -0700388 GRPC_ERROR_REF(error), "lb_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700389 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillera82950e2015-09-22 12:33:20 -0700390 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
391 }
Craig Tiller5795da72015-09-17 15:27:13 -0700392}
393
Craig Tillera82950e2015-09-22 12:33:20 -0700394static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700395 grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700396 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700397
Mark D. Rothff4df062016-08-22 15:02:49 -0700398 gpr_mu_lock(&w->chand->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700399 on_lb_policy_state_changed_locked(exec_ctx, w, error);
Mark D. Rothff4df062016-08-22 15:02:49 -0700400 gpr_mu_unlock(&w->chand->mu);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700401
Craig Tiller906e3bc2015-11-24 07:31:31 -0800402 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700403 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700404}
405
Craig Tillera82950e2015-09-22 12:33:20 -0700406static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
407 grpc_lb_policy *lb_policy,
408 grpc_connectivity_state current_state) {
409 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800410 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700411
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700412 w->chand = chand;
Craig Tillera82950e2015-09-22 12:33:20 -0700413 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700414 w->state = current_state;
415 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700416 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
417 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700418}
419
Mark D. Rothff4df062016-08-22 15:02:49 -0700420static void cc_on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
421 grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700422 channel_data *chand = arg;
423 grpc_lb_policy *lb_policy = NULL;
424 grpc_lb_policy *old_lb_policy;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700425 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700426 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700427 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Craig Tiller3f475422015-06-25 10:43:05 -0700428
Mark D. Rothff4df062016-08-22 15:02:49 -0700429 if (chand->resolver_result != NULL) {
Mark D. Rotha275aea2016-08-23 12:30:45 -0700430 lb_policy = grpc_resolver_result_get_lb_policy(chand->resolver_result);
Craig Tillera82950e2015-09-22 12:33:20 -0700431 if (lb_policy != NULL) {
432 GRPC_LB_POLICY_REF(lb_policy, "channel");
433 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700434 GRPC_ERROR_UNREF(state_error);
Craig Tiller804ff712016-05-05 16:25:40 -0700435 state =
436 grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700437 }
Craig Tiller3f475422015-06-25 10:43:05 -0700438
Mark D. Rothff4df062016-08-22 15:02:49 -0700439 grpc_resolver_result_unref(exec_ctx, chand->resolver_result);
Craig Tillera82950e2015-09-22 12:33:20 -0700440 }
441
Mark D. Rothff4df062016-08-22 15:02:49 -0700442 chand->resolver_result = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700443
Craig Tiller86c99582015-11-25 15:22:26 -0800444 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800445 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
446 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800447 }
448
Mark D. Rothff4df062016-08-22 15:02:49 -0700449 gpr_mu_lock(&chand->mu);
Craig Tiller3f475422015-06-25 10:43:05 -0700450 old_lb_policy = chand->lb_policy;
451 chand->lb_policy = lb_policy;
Craig Tiller0ede5452016-04-23 12:21:45 -0700452 if (lb_policy != NULL) {
453 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
454 NULL);
455 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700456 grpc_closure_list_fail_all(
457 &chand->waiting_for_config_closures,
458 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller6c396862016-01-28 13:53:40 -0800459 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
460 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700461 }
462 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
463 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700464 exit_idle = true;
465 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700466 }
Craig Tiller98465032015-06-29 14:36:42 -0700467
Craig Tiller804ff712016-05-05 16:25:40 -0700468 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700469 set_channel_connectivity_state_locked(
470 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700471 if (lb_policy != NULL) {
472 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700473 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800474 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Rotha275aea2016-08-23 12:30:45 -0700475 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700476 &chand->on_resolver_result_changed);
477 gpr_mu_unlock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700478 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800479 if (chand->resolver != NULL) {
480 grpc_resolver_shutdown(exec_ctx, chand->resolver);
481 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
482 chand->resolver = NULL;
483 }
Craig Tiller804ff712016-05-05 16:25:40 -0700484 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800485 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700486 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700487 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
488 GPR_ARRAY_SIZE(refs)),
489 "resolver_gone");
Mark D. Rothff4df062016-08-22 15:02:49 -0700490 gpr_mu_unlock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700491 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700492
Craig Tillera82950e2015-09-22 12:33:20 -0700493 if (exit_idle) {
494 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
495 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
496 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700497
Craig Tillera82950e2015-09-22 12:33:20 -0700498 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800499 grpc_pollset_set_del_pollset_set(
500 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700501 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
502 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700503
Craig Tillera82950e2015-09-22 12:33:20 -0700504 if (lb_policy != NULL) {
505 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
506 }
Craig Tiller45724b32015-09-22 10:42:19 -0700507
Craig Tiller906e3bc2015-11-24 07:31:31 -0800508 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700509 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700510}
511
Craig Tillera82950e2015-09-22 12:33:20 -0700512static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
513 grpc_channel_element *elem,
514 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700515 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700516
Craig Tiller332f1b32016-05-24 13:21:21 -0700517 grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700518
Craig Tillerd7f12e32016-03-03 10:08:31 -0800519 GPR_ASSERT(op->set_accept_stream == false);
Craig Tiller28bf8912015-12-07 16:07:04 -0800520 if (op->bind_pollset != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800521 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
Craig Tillere2c62372015-12-07 16:11:03 -0800522 op->bind_pollset);
Craig Tiller28bf8912015-12-07 16:07:04 -0800523 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700524
Mark D. Rothff4df062016-08-22 15:02:49 -0700525 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700526 if (op->on_connectivity_state_change != NULL) {
527 grpc_connectivity_state_notify_on_state_change(
528 exec_ctx, &chand->state_tracker, op->connectivity_state,
529 op->on_connectivity_state_change);
530 op->on_connectivity_state_change = NULL;
531 op->connectivity_state = NULL;
532 }
533
Craig Tiller26dab312015-12-07 14:43:47 -0800534 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800535 if (chand->lb_policy == NULL) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700536 grpc_exec_ctx_sched(exec_ctx, op->send_ping,
537 GRPC_ERROR_CREATE("Ping with no load balancing"),
538 NULL);
Craig Tiller26dab312015-12-07 14:43:47 -0800539 } else {
Craig Tiller28bf8912015-12-07 16:07:04 -0800540 grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800541 op->bind_pollset = NULL;
542 }
543 op->send_ping = NULL;
544 }
545
Craig Tiller1c51edc2016-05-07 16:18:43 -0700546 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
547 if (chand->resolver != NULL) {
548 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700549 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700550 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
551 grpc_resolver_shutdown(exec_ctx, chand->resolver);
552 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
553 chand->resolver = NULL;
554 if (!chand->started_resolving) {
555 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
556 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700557 grpc_exec_ctx_enqueue_list(exec_ctx,
558 &chand->waiting_for_config_closures, NULL);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700559 }
560 if (chand->lb_policy != NULL) {
561 grpc_pollset_set_del_pollset_set(exec_ctx,
562 chand->lb_policy->interested_parties,
563 chand->interested_parties);
564 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
565 chand->lb_policy = NULL;
566 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700567 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700568 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700569 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700570 gpr_mu_unlock(&chand->mu);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700571}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800572
Craig Tiller577c9b22015-11-02 14:11:15 -0800573typedef struct {
574 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800575 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800576 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800577 grpc_closure *on_ready;
578 grpc_call_element *elem;
579 grpc_closure closure;
580} continue_picking_args;
581
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700582static bool cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
583 grpc_metadata_batch *initial_metadata,
584 uint32_t initial_metadata_flags,
585 grpc_connected_subchannel **connected_subchannel,
586 grpc_closure *on_ready);
Craig Tiller577c9b22015-11-02 14:11:15 -0800587
Craig Tiller804ff712016-05-05 16:25:40 -0700588static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
589 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800590 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700591 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800592 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700593 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700594 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800595 } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800596 cpa->initial_metadata_flags,
Craig Tillerb5585d42015-11-17 07:18:31 -0800597 cpa->connected_subchannel, cpa->on_ready)) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700598 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800599 }
600 gpr_free(cpa);
601}
602
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700603static bool cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
604 grpc_metadata_batch *initial_metadata,
605 uint32_t initial_metadata_flags,
606 grpc_connected_subchannel **connected_subchannel,
607 grpc_closure *on_ready) {
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700608 GPR_TIMER_BEGIN("cc_pick_subchannel", 0);
609
Craig Tiller577c9b22015-11-02 14:11:15 -0800610 grpc_call_element *elem = elemp;
611 channel_data *chand = elem->channel_data;
612 call_data *calld = elem->call_data;
613 continue_picking_args *cpa;
614 grpc_closure *closure;
615
Craig Tillerb5585d42015-11-17 07:18:31 -0800616 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800617
Mark D. Rothff4df062016-08-22 15:02:49 -0700618 gpr_mu_lock(&chand->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800619 if (initial_metadata == NULL) {
620 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800621 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
622 connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800623 }
624 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700625 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800626 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800627 if (cpa->connected_subchannel == connected_subchannel) {
628 cpa->connected_subchannel = NULL;
Craig Tiller332f1b32016-05-24 13:21:21 -0700629 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready,
630 GRPC_ERROR_CREATE("Pick cancelled"), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800631 }
632 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700633 gpr_mu_unlock(&chand->mu);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700634 GPR_TIMER_END("cc_pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700635 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800636 }
637 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800638 grpc_lb_policy *lb_policy = chand->lb_policy;
639 int r;
640 GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel");
Mark D. Rothff4df062016-08-22 15:02:49 -0700641 gpr_mu_unlock(&chand->mu);
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700642 r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollent,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800643 initial_metadata, initial_metadata_flags,
644 connected_subchannel, on_ready);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800645 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700646 GPR_TIMER_END("cc_pick_subchannel", 0);
Craig Tiller577c9b22015-11-02 14:11:15 -0800647 return r;
648 }
649 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700650 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800651 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Rotha275aea2016-08-23 12:30:45 -0700652 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700653 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800654 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700655 if (chand->resolver != NULL) {
656 cpa = gpr_malloc(sizeof(*cpa));
657 cpa->initial_metadata = initial_metadata;
658 cpa->initial_metadata_flags = initial_metadata_flags;
659 cpa->connected_subchannel = connected_subchannel;
660 cpa->on_ready = on_ready;
661 cpa->elem = elem;
662 grpc_closure_init(&cpa->closure, continue_picking, cpa);
Craig Tiller804ff712016-05-05 16:25:40 -0700663 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
664 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700665 } else {
Craig Tiller332f1b32016-05-24 13:21:21 -0700666 grpc_exec_ctx_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"),
667 NULL);
Craig Tiller0eab6972016-04-23 12:59:57 -0700668 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700669 gpr_mu_unlock(&chand->mu);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700670
671 GPR_TIMER_END("cc_pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700672 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800673}
674
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800675/* Constructor for call_data */
Mark D. Roth76d24422016-06-23 13:22:10 -0700676static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
Mark D. Roth0badbe82016-06-23 10:15:12 -0700677 grpc_call_element *elem,
678 grpc_call_element_args *args) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700679 call_data *calld = elem->call_data;
680 gpr_atm_rel_store(&calld->subchannel_call, 0);
681 calld->pick_subchannel = cc_pick_subchannel;
682 calld->pick_subchannel_arg = elem;
683 gpr_mu_init(&calld->mu);
684 calld->connected_subchannel = NULL;
685 calld->waiting_ops = NULL;
686 calld->waiting_ops_count = 0;
687 calld->waiting_ops_capacity = 0;
688 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
689 calld->owning_call = args->call_stack;
690 calld->pollent = NULL;
Mark D. Roth0badbe82016-06-23 10:15:12 -0700691 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800692}
693
694/* Destructor for call_data */
Craig Tiller2c8063c2016-03-22 22:12:15 -0700695static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700696 const grpc_call_final_info *final_info,
Craig Tiller2c8063c2016-03-22 22:12:15 -0700697 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700698 call_data *calld = elem->call_data;
699 grpc_subchannel_call *call = GET_CALL(calld);
700 if (call != NULL && call != CANCELLED_CALL) {
701 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
702 }
703 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
704 gpr_mu_destroy(&calld->mu);
705 GPR_ASSERT(calld->waiting_ops_count == 0);
706 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700707 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800708}
709
710/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700711static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800712 grpc_channel_element *elem,
713 grpc_channel_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800714 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800715
Craig Tillera82950e2015-09-22 12:33:20 -0700716 memset(chand, 0, sizeof(*chand));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700717
Craig Tiller577c9b22015-11-02 14:11:15 -0800718 GPR_ASSERT(args->is_last);
Craig Tillera82950e2015-09-22 12:33:20 -0700719 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800720
Mark D. Rothff4df062016-08-22 15:02:49 -0700721 gpr_mu_init(&chand->mu);
722 grpc_closure_init(&chand->on_resolver_result_changed,
723 cc_on_resolver_result_changed, chand);
Craig Tiller11beb9a2015-11-24 10:29:32 -0800724 chand->owning_stack = args->channel_stack;
Craig Tiller98465032015-06-29 14:36:42 -0700725
Craig Tillera82950e2015-09-22 12:33:20 -0700726 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
727 "client_channel");
Craig Tiller69b093b2016-02-25 19:04:07 -0800728 chand->interested_parties = grpc_pollset_set_create();
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800729}
730
731/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700732static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
733 grpc_channel_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800734 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800735
Craig Tillera82950e2015-09-22 12:33:20 -0700736 if (chand->resolver != NULL) {
737 grpc_resolver_shutdown(exec_ctx, chand->resolver);
738 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
739 }
740 if (chand->lb_policy != NULL) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800741 grpc_pollset_set_del_pollset_set(exec_ctx,
Craig Tiller69b093b2016-02-25 19:04:07 -0800742 chand->lb_policy->interested_parties,
743 chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700744 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
745 }
746 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller69b093b2016-02-25 19:04:07 -0800747 grpc_pollset_set_destroy(chand->interested_parties);
Mark D. Rothff4df062016-08-22 15:02:49 -0700748 gpr_mu_destroy(&chand->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800749}
750
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700751static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
752 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700753 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800754 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700755 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -0800756}
757
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800758const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -0700759 cc_start_transport_stream_op,
760 cc_start_transport_op,
761 sizeof(call_data),
762 init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700763 cc_set_pollset_or_pollset_set,
Craig Tillerf40df232016-03-25 13:38:14 -0700764 destroy_call_elem,
765 sizeof(channel_data),
766 init_channel_elem,
767 destroy_channel_elem,
768 cc_get_peer,
769 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -0700770};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800771
Craig Tillera82950e2015-09-22 12:33:20 -0700772void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
773 grpc_channel_stack *channel_stack,
774 grpc_resolver *resolver) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800775 /* post construction initialization: set the transport setup pointer */
Craig Tillera82950e2015-09-22 12:33:20 -0700776 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800777 channel_data *chand = elem->channel_data;
Mark D. Rothff4df062016-08-22 15:02:49 -0700778 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700779 GPR_ASSERT(!chand->resolver);
Craig Tillerf5f17122015-06-25 08:47:26 -0700780 chand->resolver = resolver;
Craig Tillera82950e2015-09-22 12:33:20 -0700781 GRPC_RESOLVER_REF(resolver, "channel");
782 if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
783 chand->exit_idle_when_lb_policy_arrives) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700784 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800785 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Rothff4df062016-08-22 15:02:49 -0700786 grpc_resolver_next(exec_ctx, resolver, &chand->resolver_result,
787 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700788 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700789 gpr_mu_unlock(&chand->mu);
Craig Tiller190d3602015-02-18 09:23:38 -0800790}
Craig Tiller48cb07c2015-07-15 16:16:15 -0700791
Craig Tillera82950e2015-09-22 12:33:20 -0700792grpc_connectivity_state grpc_client_channel_check_connectivity_state(
793 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700794 channel_data *chand = elem->channel_data;
795 grpc_connectivity_state out;
Mark D. Rothff4df062016-08-22 15:02:49 -0700796 gpr_mu_lock(&chand->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700797 out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700798 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
799 if (chand->lb_policy != NULL) {
800 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
801 } else {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700802 chand->exit_idle_when_lb_policy_arrives = true;
Craig Tillera82950e2015-09-22 12:33:20 -0700803 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800804 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700805 chand->started_resolving = true;
Mark D. Rotha275aea2016-08-23 12:30:45 -0700806 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700807 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700808 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700809 }
Craig Tillera82950e2015-09-22 12:33:20 -0700810 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700811 gpr_mu_unlock(&chand->mu);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700812 return out;
813}
814
Craig Tiller86c99582015-11-25 15:22:26 -0800815typedef struct {
816 channel_data *chand;
817 grpc_pollset *pollset;
818 grpc_closure *on_complete;
819 grpc_closure my_closure;
820} external_connectivity_watcher;
821
Craig Tiller1d881fb2015-12-01 07:39:04 -0800822static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700823 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -0800824 external_connectivity_watcher *w = arg;
825 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -0800826 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800827 w->pollset);
828 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
829 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -0800830 gpr_free(w);
Craig Tiller804ff712016-05-05 16:25:40 -0700831 follow_up->cb(exec_ctx, follow_up->cb_arg, error);
Craig Tiller86c99582015-11-25 15:22:26 -0800832}
833
Craig Tillera82950e2015-09-22 12:33:20 -0700834void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -0800835 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -0700836 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700837 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -0800838 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
839 w->chand = chand;
840 w->pollset = pollset;
841 w->on_complete = on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -0800842 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller86c99582015-11-25 15:22:26 -0800843 grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
Craig Tiller1d881fb2015-12-01 07:39:04 -0800844 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
845 "external_connectivity_watcher");
Mark D. Rothff4df062016-08-22 15:02:49 -0700846 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700847 grpc_connectivity_state_notify_on_state_change(
Craig Tiller86c99582015-11-25 15:22:26 -0800848 exec_ctx, &chand->state_tracker, state, &w->my_closure);
Mark D. Rothff4df062016-08-22 15:02:49 -0700849 gpr_mu_unlock(&chand->mu);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700850}