blob: 5fec87c67c0280cfea0b2547db592bfe1f26f989 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * 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
34#include "src/core/channel/client_channel.h"
35
36#include <stdio.h>
Craig Tillereb3b12e2015-06-26 14:42:49 -070037#include <string.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080039#include <grpc/support/alloc.h>
40#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080041#include <grpc/support/sync.h>
42#include <grpc/support/useful.h>
43
Craig Tiller8910ac62015-10-08 16:49:15 -070044#include "src/core/channel/channel_args.h"
45#include "src/core/channel/connected_channel.h"
Craig Tiller577c9b22015-11-02 14:11:15 -080046#include "src/core/channel/subchannel_call_holder.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070047#include "src/core/iomgr/iomgr.h"
48#include "src/core/profiling/timers.h"
49#include "src/core/support/string.h"
50#include "src/core/surface/channel.h"
51#include "src/core/transport/connectivity_state.h"
52
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080053/* Client channel implementation */
54
Craig Tiller577c9b22015-11-02 14:11:15 -080055typedef grpc_subchannel_call_holder call_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056
Craig Tiller800dacb2015-10-06 09:10:26 -070057typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -070058 /** resolver for this channel */
59 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -070060 /** have we started resolving this channel */
61 int started_resolving;
Craig Tillerf5f17122015-06-25 08:47:26 -070062
Craig Tiller9d94b602015-07-01 14:23:18 -070063 /** mutex protecting client configuration, including all
64 variables below in this data structure */
Craig Tillerf5f17122015-06-25 08:47:26 -070065 gpr_mu mu_config;
Craig Tillerf5f17122015-06-25 08:47:26 -070066 /** currently active load balancer - guarded by mu_config */
67 grpc_lb_policy *lb_policy;
Craig Tillerf5f17122015-06-25 08:47:26 -070068 /** incoming configuration - set by resolver.next
69 guarded by mu_config */
70 grpc_client_config *incoming_configuration;
Craig Tiller3f475422015-06-25 10:43:05 -070071 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -070072 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -070073 /** resolver callback */
Craig Tiller33825112015-09-18 07:44:19 -070074 grpc_closure on_config_changed;
Craig Tiller3f475422015-06-25 10:43:05 -070075 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -070076 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -070077 /** when an lb_policy arrives, should we try to exit idle */
78 int exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -080079 /** owning stack */
80 grpc_channel_stack *owning_stack;
Craig Tiller86c99582015-11-25 15:22:26 -080081 /** interested parties */
82 grpc_pollset_set interested_parties;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080083} channel_data;
84
Craig Tillerd6c98df2015-08-18 09:33:44 -070085/** We create one watcher for each new lb_policy that is returned from a
86 resolver,
87 to watch for state changes from the lb_policy. When a state change is seen,
88 we
Craig Tiller1ada6ad2015-07-16 16:19:14 -070089 update the channel, and create a new watcher */
Craig Tillera82950e2015-09-22 12:33:20 -070090typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -070091 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -070092 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070093 grpc_connectivity_state state;
94 grpc_lb_policy *lb_policy;
95} lb_policy_connectivity_watcher;
96
Craig Tillera82950e2015-09-22 12:33:20 -070097typedef struct {
Craig Tiller33825112015-09-18 07:44:19 -070098 grpc_closure closure;
Craig Tillereb3b12e2015-06-26 14:42:49 -070099 grpc_call_element *elem;
100} waiting_call;
101
Craig Tillera82950e2015-09-22 12:33:20 -0700102static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800103 return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700104}
Craig Tillerf5f17122015-06-25 08:47:26 -0700105
Craig Tillera82950e2015-09-22 12:33:20 -0700106static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
107 grpc_call_element *elem,
108 grpc_transport_stream_op *op) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800109 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
110 grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800111}
112
Craig Tillera82950e2015-09-22 12:33:20 -0700113static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
114 grpc_lb_policy *lb_policy,
115 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700116
Craig Tillera82950e2015-09-22 12:33:20 -0700117static void on_lb_policy_state_changed_locked(
118 grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800119 grpc_connectivity_state publish_state = w->state;
Craig Tiller5795da72015-09-17 15:27:13 -0700120 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700121 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700122
Craig Tilleree7531c2015-11-25 09:48:15 -0800123 if (publish_state == GRPC_CHANNEL_FATAL_FAILURE && w->chand->resolver != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800124 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
125 grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
126 }
127 grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, publish_state,
Craig Tillera82950e2015-09-22 12:33:20 -0700128 "lb_changed");
129 if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
130 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
131 }
Craig Tiller5795da72015-09-17 15:27:13 -0700132}
133
Craig Tillera82950e2015-09-22 12:33:20 -0700134static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
135 int iomgr_success) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700136 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700137
Craig Tillera82950e2015-09-22 12:33:20 -0700138 gpr_mu_lock(&w->chand->mu_config);
139 on_lb_policy_state_changed_locked(exec_ctx, w);
140 gpr_mu_unlock(&w->chand->mu_config);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700141
Craig Tiller906e3bc2015-11-24 07:31:31 -0800142 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700143 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700144}
145
Craig Tillera82950e2015-09-22 12:33:20 -0700146static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
147 grpc_lb_policy *lb_policy,
148 grpc_connectivity_state current_state) {
149 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800150 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700151
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700152 w->chand = chand;
Craig Tillera82950e2015-09-22 12:33:20 -0700153 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700154 w->state = current_state;
155 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700156 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
157 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700158}
159
Craig Tillera82950e2015-09-22 12:33:20 -0700160static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
161 int iomgr_success) {
Craig Tiller3f475422015-06-25 10:43:05 -0700162 channel_data *chand = arg;
163 grpc_lb_policy *lb_policy = NULL;
164 grpc_lb_policy *old_lb_policy;
165 grpc_resolver *old_resolver;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700166 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700167 int exit_idle = 0;
Craig Tiller3f475422015-06-25 10:43:05 -0700168
Craig Tillera82950e2015-09-22 12:33:20 -0700169 if (chand->incoming_configuration != NULL) {
170 lb_policy = grpc_client_config_get_lb_policy(chand->incoming_configuration);
171 if (lb_policy != NULL) {
172 GRPC_LB_POLICY_REF(lb_policy, "channel");
173 GRPC_LB_POLICY_REF(lb_policy, "config_change");
174 state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
Craig Tiller45724b32015-09-22 10:42:19 -0700175 }
Craig Tiller3f475422015-06-25 10:43:05 -0700176
Craig Tillera82950e2015-09-22 12:33:20 -0700177 grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
178 }
179
Craig Tiller3f475422015-06-25 10:43:05 -0700180 chand->incoming_configuration = NULL;
181
Craig Tiller86c99582015-11-25 15:22:26 -0800182 if (lb_policy != NULL) {
183 grpc_pollset_set_add_pollset_set(exec_ctx, &lb_policy->interested_parties, &chand->interested_parties);
184 }
185
Craig Tillera82950e2015-09-22 12:33:20 -0700186 gpr_mu_lock(&chand->mu_config);
Craig Tiller3f475422015-06-25 10:43:05 -0700187 old_lb_policy = chand->lb_policy;
188 chand->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700189 if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) {
190 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures);
191 }
192 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
193 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
194 exit_idle = 1;
195 chand->exit_idle_when_lb_policy_arrives = 0;
196 }
Craig Tiller98465032015-06-29 14:36:42 -0700197
Craig Tillera82950e2015-09-22 12:33:20 -0700198 if (iomgr_success && chand->resolver) {
199 grpc_resolver *resolver = chand->resolver;
200 GRPC_RESOLVER_REF(resolver, "channel-next");
201 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
202 "new_lb+resolver");
203 if (lb_policy != NULL) {
204 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700205 }
Craig Tillera82950e2015-09-22 12:33:20 -0700206 gpr_mu_unlock(&chand->mu_config);
Craig Tiller906e3bc2015-11-24 07:31:31 -0800207 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700208 grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
209 &chand->on_config_changed);
210 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
211 } else {
212 old_resolver = chand->resolver;
213 chand->resolver = NULL;
214 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
215 GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
216 gpr_mu_unlock(&chand->mu_config);
217 if (old_resolver != NULL) {
218 grpc_resolver_shutdown(exec_ctx, old_resolver);
219 GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
Craig Tiller45724b32015-09-22 10:42:19 -0700220 }
Craig Tillera82950e2015-09-22 12:33:20 -0700221 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700222
Craig Tillera82950e2015-09-22 12:33:20 -0700223 if (exit_idle) {
224 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
225 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
226 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700227
Craig Tillera82950e2015-09-22 12:33:20 -0700228 if (old_lb_policy != NULL) {
Craig Tiller86c99582015-11-25 15:22:26 -0800229 grpc_pollset_set_del_pollset_set(exec_ctx, &old_lb_policy->interested_parties, &chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700230 grpc_lb_policy_shutdown(exec_ctx, old_lb_policy);
231 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
232 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700233
Craig Tillera82950e2015-09-22 12:33:20 -0700234 if (lb_policy != NULL) {
235 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
236 }
Craig Tiller45724b32015-09-22 10:42:19 -0700237
Craig Tiller906e3bc2015-11-24 07:31:31 -0800238 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller3f475422015-06-25 10:43:05 -0700239}
240
Craig Tillera82950e2015-09-22 12:33:20 -0700241static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
242 grpc_channel_element *elem,
243 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700244 grpc_lb_policy *lb_policy = NULL;
245 channel_data *chand = elem->channel_data;
Craig Tiller98465032015-06-29 14:36:42 -0700246 grpc_resolver *destroy_resolver = NULL;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700247
Craig Tillera82950e2015-09-22 12:33:20 -0700248 grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700249
Craig Tillera82950e2015-09-22 12:33:20 -0700250 GPR_ASSERT(op->set_accept_stream == NULL);
251 GPR_ASSERT(op->bind_pollset == NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700252
Craig Tillera82950e2015-09-22 12:33:20 -0700253 gpr_mu_lock(&chand->mu_config);
254 if (op->on_connectivity_state_change != NULL) {
255 grpc_connectivity_state_notify_on_state_change(
256 exec_ctx, &chand->state_tracker, op->connectivity_state,
257 op->on_connectivity_state_change);
258 op->on_connectivity_state_change = NULL;
259 op->connectivity_state = NULL;
260 }
261
Craig Tiller577c9b22015-11-02 14:11:15 -0800262 lb_policy = chand->lb_policy;
263 if (lb_policy) {
264 GRPC_LB_POLICY_REF(lb_policy, "broadcast");
Craig Tillera82950e2015-09-22 12:33:20 -0700265 }
Craig Tiller03dc6552015-07-17 23:12:34 -0700266
Craig Tillera82950e2015-09-22 12:33:20 -0700267 if (op->disconnect && chand->resolver != NULL) {
268 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
269 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
270 destroy_resolver = chand->resolver;
271 chand->resolver = NULL;
272 if (chand->lb_policy != NULL) {
Craig Tiller86c99582015-11-25 15:22:26 -0800273 grpc_pollset_set_del_pollset_set(exec_ctx, &chand->lb_policy->interested_parties, &chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700274 grpc_lb_policy_shutdown(exec_ctx, chand->lb_policy);
275 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
276 chand->lb_policy = NULL;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700277 }
Craig Tillera82950e2015-09-22 12:33:20 -0700278 }
279 gpr_mu_unlock(&chand->mu_config);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700280
Craig Tillera82950e2015-09-22 12:33:20 -0700281 if (destroy_resolver) {
282 grpc_resolver_shutdown(exec_ctx, destroy_resolver);
283 GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
284 }
Craig Tiller98465032015-06-29 14:36:42 -0700285
Craig Tillera82950e2015-09-22 12:33:20 -0700286 if (lb_policy) {
287 grpc_lb_policy_broadcast(exec_ctx, lb_policy, op);
288 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "broadcast");
289 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700290}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800291
Craig Tiller577c9b22015-11-02 14:11:15 -0800292typedef struct {
293 grpc_metadata_batch *initial_metadata;
Craig Tillerb5585d42015-11-17 07:18:31 -0800294 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800295 grpc_closure *on_ready;
296 grpc_call_element *elem;
297 grpc_closure closure;
298} continue_picking_args;
299
300static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
301 grpc_metadata_batch *initial_metadata,
Craig Tillerb5585d42015-11-17 07:18:31 -0800302 grpc_connected_subchannel **connected_subchannel,
Craig Tiller577c9b22015-11-02 14:11:15 -0800303 grpc_closure *on_ready);
304
305static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, int success) {
306 continue_picking_args *cpa = arg;
307 if (!success) {
308 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
Craig Tillerb5585d42015-11-17 07:18:31 -0800309 } else if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800310 /* cancelled, do nothing */
311 } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
Craig Tillerb5585d42015-11-17 07:18:31 -0800312 cpa->connected_subchannel, cpa->on_ready)) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800313 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 1);
314 }
315 gpr_free(cpa);
316}
317
318static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
319 grpc_metadata_batch *initial_metadata,
Craig Tillerb5585d42015-11-17 07:18:31 -0800320 grpc_connected_subchannel **connected_subchannel,
Craig Tiller577c9b22015-11-02 14:11:15 -0800321 grpc_closure *on_ready) {
322 grpc_call_element *elem = elemp;
323 channel_data *chand = elem->channel_data;
324 call_data *calld = elem->call_data;
325 continue_picking_args *cpa;
326 grpc_closure *closure;
327
Craig Tillerb5585d42015-11-17 07:18:31 -0800328 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800329
330 gpr_mu_lock(&chand->mu_config);
331 if (initial_metadata == NULL) {
332 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800333 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
334 connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800335 }
336 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
337 closure = grpc_closure_next(closure)) {
338 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800339 if (cpa->connected_subchannel == connected_subchannel) {
340 cpa->connected_subchannel = NULL;
Craig Tiller577c9b22015-11-02 14:11:15 -0800341 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
342 }
343 }
344 gpr_mu_unlock(&chand->mu_config);
345 return 1;
346 }
347 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800348 int r =
349 grpc_lb_policy_pick(exec_ctx, chand->lb_policy, calld->pollset,
350 initial_metadata, connected_subchannel, on_ready);
Craig Tiller577c9b22015-11-02 14:11:15 -0800351 gpr_mu_unlock(&chand->mu_config);
352 return r;
353 }
354 if (chand->resolver != NULL && !chand->started_resolving) {
355 chand->started_resolving = 1;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800356 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tiller577c9b22015-11-02 14:11:15 -0800357 grpc_resolver_next(exec_ctx, chand->resolver,
358 &chand->incoming_configuration,
359 &chand->on_config_changed);
360 }
361 cpa = gpr_malloc(sizeof(*cpa));
362 cpa->initial_metadata = initial_metadata;
Craig Tillerb5585d42015-11-17 07:18:31 -0800363 cpa->connected_subchannel = connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800364 cpa->on_ready = on_ready;
365 cpa->elem = elem;
366 grpc_closure_init(&cpa->closure, continue_picking, cpa);
367 grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure, 1);
368 gpr_mu_unlock(&chand->mu_config);
369 return 0;
370}
371
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800372/* Constructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700373static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Craig Tiller577c9b22015-11-02 14:11:15 -0800374 grpc_call_element_args *args) {
Craig Tiller11beb9a2015-11-24 10:29:32 -0800375 grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem,
376 args->call_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800377}
378
379/* Destructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700380static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
381 grpc_call_element *elem) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800382 grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800383}
384
385/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700386static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800387 grpc_channel_element *elem,
388 grpc_channel_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800389 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800390
Craig Tillera82950e2015-09-22 12:33:20 -0700391 memset(chand, 0, sizeof(*chand));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700392
Craig Tiller577c9b22015-11-02 14:11:15 -0800393 GPR_ASSERT(args->is_last);
Craig Tillera82950e2015-09-22 12:33:20 -0700394 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800395
Craig Tillera82950e2015-09-22 12:33:20 -0700396 gpr_mu_init(&chand->mu_config);
Craig Tillera82950e2015-09-22 12:33:20 -0700397 grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
Craig Tiller11beb9a2015-11-24 10:29:32 -0800398 chand->owning_stack = args->channel_stack;
Craig Tiller98465032015-06-29 14:36:42 -0700399
Craig Tillera82950e2015-09-22 12:33:20 -0700400 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
401 "client_channel");
Craig Tiller86c99582015-11-25 15:22:26 -0800402 grpc_pollset_set_init(&chand->interested_parties);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800403}
404
405/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700406static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
407 grpc_channel_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800408 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800409
Craig Tillera82950e2015-09-22 12:33:20 -0700410 if (chand->resolver != NULL) {
411 grpc_resolver_shutdown(exec_ctx, chand->resolver);
412 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
413 }
414 if (chand->lb_policy != NULL) {
Craig Tiller86c99582015-11-25 15:22:26 -0800415 grpc_pollset_set_del_pollset_set(exec_ctx, &chand->lb_policy->interested_parties, &chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700416 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
417 }
418 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
Craig Tiller86c99582015-11-25 15:22:26 -0800419 grpc_pollset_set_destroy(&chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700420 gpr_mu_destroy(&chand->mu_config);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800421}
422
Craig Tiller577c9b22015-11-02 14:11:15 -0800423static void cc_set_pollset(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
424 grpc_pollset *pollset) {
425 call_data *calld = elem->call_data;
426 calld->pollset = pollset;
427}
428
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800429const grpc_channel_filter grpc_client_channel_filter = {
Craig Tiller71a0f9d2015-09-28 17:22:01 -0700430 cc_start_transport_stream_op, cc_start_transport_op, sizeof(call_data),
Craig Tiller577c9b22015-11-02 14:11:15 -0800431 init_call_elem, cc_set_pollset, destroy_call_elem, sizeof(channel_data),
432 init_channel_elem, destroy_channel_elem, cc_get_peer, "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -0700433};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800434
Craig Tillera82950e2015-09-22 12:33:20 -0700435void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
436 grpc_channel_stack *channel_stack,
437 grpc_resolver *resolver) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800438 /* post construction initialization: set the transport setup pointer */
Craig Tillera82950e2015-09-22 12:33:20 -0700439 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800440 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700441 gpr_mu_lock(&chand->mu_config);
442 GPR_ASSERT(!chand->resolver);
Craig Tillerf5f17122015-06-25 08:47:26 -0700443 chand->resolver = resolver;
Craig Tillera82950e2015-09-22 12:33:20 -0700444 GRPC_RESOLVER_REF(resolver, "channel");
445 if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
446 chand->exit_idle_when_lb_policy_arrives) {
447 chand->started_resolving = 1;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800448 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700449 grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
450 &chand->on_config_changed);
451 }
452 gpr_mu_unlock(&chand->mu_config);
Craig Tiller190d3602015-02-18 09:23:38 -0800453}
Craig Tiller48cb07c2015-07-15 16:16:15 -0700454
Craig Tillera82950e2015-09-22 12:33:20 -0700455grpc_connectivity_state grpc_client_channel_check_connectivity_state(
456 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700457 channel_data *chand = elem->channel_data;
458 grpc_connectivity_state out;
Craig Tillera82950e2015-09-22 12:33:20 -0700459 gpr_mu_lock(&chand->mu_config);
460 out = grpc_connectivity_state_check(&chand->state_tracker);
461 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
462 if (chand->lb_policy != NULL) {
463 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
464 } else {
465 chand->exit_idle_when_lb_policy_arrives = 1;
466 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller906e3bc2015-11-24 07:31:31 -0800467 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700468 chand->started_resolving = 1;
469 grpc_resolver_next(exec_ctx, chand->resolver,
470 &chand->incoming_configuration,
471 &chand->on_config_changed);
472 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700473 }
Craig Tillera82950e2015-09-22 12:33:20 -0700474 }
475 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700476 return out;
477}
478
Craig Tiller86c99582015-11-25 15:22:26 -0800479typedef struct {
480 channel_data *chand;
481 grpc_pollset *pollset;
482 grpc_closure *on_complete;
483 grpc_closure my_closure;
484} external_connectivity_watcher;
485
486static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg, int iomgr_success) {
487 external_connectivity_watcher *w = arg;
488 grpc_closure *follow_up = w->on_complete;
489 grpc_pollset_set_del_pollset(exec_ctx, &w->chand->interested_parties, w->pollset);
490 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "external_connectivity_watcher");
491 gpr_free(w);
492 follow_up->cb(exec_ctx, follow_up->cb_arg, iomgr_success);
493}
494
Craig Tillera82950e2015-09-22 12:33:20 -0700495void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -0800496 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -0700497 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700498 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -0800499 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
500 w->chand = chand;
501 w->pollset = pollset;
502 w->on_complete = on_complete;
503 grpc_pollset_set_add_pollset(exec_ctx, &chand->interested_parties, pollset);
504 grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
505 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, "external_connectivity_watcher");
Craig Tillera82950e2015-09-22 12:33:20 -0700506 gpr_mu_lock(&chand->mu_config);
507 grpc_connectivity_state_notify_on_state_change(
Craig Tiller86c99582015-11-25 15:22:26 -0800508 exec_ctx, &chand->state_tracker, state, &w->my_closure);
Craig Tillera82950e2015-09-22 12:33:20 -0700509 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700510}