blob: 1a22801c073819eafd6720a0dc33a8f957ccb3c7 [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 Tiller50bc6092015-07-01 14:25:19 -070062 /** master channel - the grpc_channel instance that ultimately owns
63 this channel_data via its channel stack.
64 We occasionally use this to bump the refcount on the master channel
65 to keep ourselves alive through an asynchronous operation. */
Craig Tiller98465032015-06-29 14:36:42 -070066 grpc_channel *master;
Craig Tillerf5f17122015-06-25 08:47:26 -070067
Craig Tiller9d94b602015-07-01 14:23:18 -070068 /** mutex protecting client configuration, including all
69 variables below in this data structure */
Craig Tillerf5f17122015-06-25 08:47:26 -070070 gpr_mu mu_config;
Craig Tillerf5f17122015-06-25 08:47:26 -070071 /** currently active load balancer - guarded by mu_config */
72 grpc_lb_policy *lb_policy;
Craig Tillerf5f17122015-06-25 08:47:26 -070073 /** incoming configuration - set by resolver.next
74 guarded by mu_config */
75 grpc_client_config *incoming_configuration;
Craig Tiller3f475422015-06-25 10:43:05 -070076 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -070077 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -070078 /** resolver callback */
Craig Tiller33825112015-09-18 07:44:19 -070079 grpc_closure on_config_changed;
Craig Tiller3f475422015-06-25 10:43:05 -070080 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -070081 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -070082 /** when an lb_policy arrives, should we try to exit idle */
83 int exit_idle_when_lb_policy_arrives;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070084 /** pollset_set of interested parties in a new connection */
85 grpc_pollset_set pollset_set;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080086} channel_data;
87
Craig Tillerd6c98df2015-08-18 09:33:44 -070088/** We create one watcher for each new lb_policy that is returned from a
89 resolver,
90 to watch for state changes from the lb_policy. When a state change is seen,
91 we
Craig Tiller1ada6ad2015-07-16 16:19:14 -070092 update the channel, and create a new watcher */
Craig Tillera82950e2015-09-22 12:33:20 -070093typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -070094 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -070095 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -070096 grpc_connectivity_state state;
97 grpc_lb_policy *lb_policy;
98} lb_policy_connectivity_watcher;
99
Craig Tillera82950e2015-09-22 12:33:20 -0700100typedef struct {
Craig Tiller33825112015-09-18 07:44:19 -0700101 grpc_closure closure;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700102 grpc_call_element *elem;
103} waiting_call;
104
Craig Tillera82950e2015-09-22 12:33:20 -0700105static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
Craig Tiller1b22b9d2015-07-20 13:42:22 -0700106 channel_data *chand = elem->channel_data;
Craig Tiller577c9b22015-11-02 14:11:15 -0800107 return grpc_subchannel_call_holder_get_peer(exec_ctx, elem->call_data,
108 chand->master);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700109}
Craig Tillerf5f17122015-06-25 08:47:26 -0700110
Craig Tillera82950e2015-09-22 12:33:20 -0700111static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
112 grpc_call_element *elem,
113 grpc_transport_stream_op *op) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800114 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
115 grpc_subchannel_call_holder_perform_op(exec_ctx, elem->call_data, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800116}
117
Craig Tillera82950e2015-09-22 12:33:20 -0700118static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
119 grpc_lb_policy *lb_policy,
120 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700121
Craig Tillera82950e2015-09-22 12:33:20 -0700122static void on_lb_policy_state_changed_locked(
123 grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
Craig Tiller5795da72015-09-17 15:27:13 -0700124 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700125 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700126
Craig Tillera82950e2015-09-22 12:33:20 -0700127 grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, w->state,
128 "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 Tillera82950e2015-09-22 12:33:20 -0700142 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->chand->master, "watch_lb_policy");
143 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));
150 GRPC_CHANNEL_INTERNAL_REF(chand->master, "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 Tillera82950e2015-09-22 12:33:20 -0700182 gpr_mu_lock(&chand->mu_config);
Craig Tiller3f475422015-06-25 10:43:05 -0700183 old_lb_policy = chand->lb_policy;
184 chand->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700185 if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) {
186 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures);
187 }
188 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
189 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
190 exit_idle = 1;
191 chand->exit_idle_when_lb_policy_arrives = 0;
192 }
Craig Tiller98465032015-06-29 14:36:42 -0700193
Craig Tillera82950e2015-09-22 12:33:20 -0700194 if (iomgr_success && chand->resolver) {
195 grpc_resolver *resolver = chand->resolver;
196 GRPC_RESOLVER_REF(resolver, "channel-next");
197 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
198 "new_lb+resolver");
199 if (lb_policy != NULL) {
200 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700201 }
Craig Tillera82950e2015-09-22 12:33:20 -0700202 gpr_mu_unlock(&chand->mu_config);
203 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
204 grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
205 &chand->on_config_changed);
206 GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
207 } else {
208 old_resolver = chand->resolver;
209 chand->resolver = NULL;
210 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
211 GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
212 gpr_mu_unlock(&chand->mu_config);
213 if (old_resolver != NULL) {
214 grpc_resolver_shutdown(exec_ctx, old_resolver);
215 GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
Craig Tiller45724b32015-09-22 10:42:19 -0700216 }
Craig Tillera82950e2015-09-22 12:33:20 -0700217 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700218
Craig Tillera82950e2015-09-22 12:33:20 -0700219 if (exit_idle) {
220 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
221 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
222 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700223
Craig Tillera82950e2015-09-22 12:33:20 -0700224 if (old_lb_policy != NULL) {
225 grpc_lb_policy_shutdown(exec_ctx, old_lb_policy);
226 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
227 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700228
Craig Tillera82950e2015-09-22 12:33:20 -0700229 if (lb_policy != NULL) {
230 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
231 }
Craig Tiller45724b32015-09-22 10:42:19 -0700232
Craig Tillera82950e2015-09-22 12:33:20 -0700233 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->master, "resolver");
Craig Tiller3f475422015-06-25 10:43:05 -0700234}
235
Craig Tillera82950e2015-09-22 12:33:20 -0700236static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
237 grpc_channel_element *elem,
238 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700239 grpc_lb_policy *lb_policy = NULL;
240 channel_data *chand = elem->channel_data;
Craig Tiller98465032015-06-29 14:36:42 -0700241 grpc_resolver *destroy_resolver = NULL;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700242
Craig Tillera82950e2015-09-22 12:33:20 -0700243 grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700244
Craig Tillera82950e2015-09-22 12:33:20 -0700245 GPR_ASSERT(op->set_accept_stream == NULL);
Craig Tiller26dab312015-12-07 14:43:47 -0800246 GPR_ASSERT(op->bind_pollset == NULL || op->send_ping != NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700247
Craig Tillera82950e2015-09-22 12:33:20 -0700248 gpr_mu_lock(&chand->mu_config);
249 if (op->on_connectivity_state_change != NULL) {
250 grpc_connectivity_state_notify_on_state_change(
251 exec_ctx, &chand->state_tracker, op->connectivity_state,
252 op->on_connectivity_state_change);
253 op->on_connectivity_state_change = NULL;
254 op->connectivity_state = NULL;
255 }
256
Craig Tiller577c9b22015-11-02 14:11:15 -0800257 lb_policy = chand->lb_policy;
258 if (lb_policy) {
259 GRPC_LB_POLICY_REF(lb_policy, "broadcast");
Craig Tillera82950e2015-09-22 12:33:20 -0700260 }
Craig Tiller03dc6552015-07-17 23:12:34 -0700261
Craig Tiller26dab312015-12-07 14:43:47 -0800262 if (op->send_ping != NULL) {
263 if (lb_policy == NULL) {
264 grpc_exec_ctx_enqueue(exec_ctx, op->send_ping, 0);
265 } else {
266 grpc_lb_policy_ping_one(exec_ctx, lb_policy, op->bind_pollset, op->send_ping);
267 op->bind_pollset = NULL;
268 }
269 op->send_ping = NULL;
270 }
271
Craig Tillera82950e2015-09-22 12:33:20 -0700272 if (op->disconnect && chand->resolver != NULL) {
273 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
274 GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
275 destroy_resolver = chand->resolver;
276 chand->resolver = NULL;
277 if (chand->lb_policy != NULL) {
278 grpc_lb_policy_shutdown(exec_ctx, chand->lb_policy);
279 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
280 chand->lb_policy = NULL;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700281 }
Craig Tillera82950e2015-09-22 12:33:20 -0700282 }
283 gpr_mu_unlock(&chand->mu_config);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700284
Craig Tillera82950e2015-09-22 12:33:20 -0700285 if (destroy_resolver) {
286 grpc_resolver_shutdown(exec_ctx, destroy_resolver);
287 GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
288 }
Craig Tiller98465032015-06-29 14:36:42 -0700289
Craig Tillera82950e2015-09-22 12:33:20 -0700290 if (lb_policy) {
291 grpc_lb_policy_broadcast(exec_ctx, lb_policy, op);
292 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "broadcast");
293 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700294}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800295
Craig Tiller577c9b22015-11-02 14:11:15 -0800296typedef struct {
297 grpc_metadata_batch *initial_metadata;
298 grpc_subchannel **subchannel;
299 grpc_closure *on_ready;
300 grpc_call_element *elem;
301 grpc_closure closure;
302} continue_picking_args;
303
304static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
305 grpc_metadata_batch *initial_metadata,
306 grpc_subchannel **subchannel,
307 grpc_closure *on_ready);
308
309static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, int success) {
310 continue_picking_args *cpa = arg;
311 if (!success) {
312 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
313 } else if (cpa->subchannel == NULL) {
314 /* cancelled, do nothing */
315 } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
316 cpa->subchannel, cpa->on_ready)) {
317 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 1);
318 }
319 gpr_free(cpa);
320}
321
322static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
323 grpc_metadata_batch *initial_metadata,
324 grpc_subchannel **subchannel,
325 grpc_closure *on_ready) {
326 grpc_call_element *elem = elemp;
327 channel_data *chand = elem->channel_data;
328 call_data *calld = elem->call_data;
329 continue_picking_args *cpa;
330 grpc_closure *closure;
331
332 GPR_ASSERT(subchannel);
333
334 gpr_mu_lock(&chand->mu_config);
335 if (initial_metadata == NULL) {
336 if (chand->lb_policy != NULL) {
337 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy, subchannel);
338 }
339 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
340 closure = grpc_closure_next(closure)) {
341 cpa = closure->cb_arg;
342 if (cpa->subchannel == subchannel) {
343 cpa->subchannel = NULL;
344 grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, 0);
345 }
346 }
347 gpr_mu_unlock(&chand->mu_config);
348 return 1;
349 }
350 if (chand->lb_policy != NULL) {
351 int r = grpc_lb_policy_pick(exec_ctx, chand->lb_policy, calld->pollset,
352 initial_metadata, subchannel, on_ready);
353 gpr_mu_unlock(&chand->mu_config);
354 return r;
355 }
356 if (chand->resolver != NULL && !chand->started_resolving) {
357 chand->started_resolving = 1;
358 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
359 grpc_resolver_next(exec_ctx, chand->resolver,
360 &chand->incoming_configuration,
361 &chand->on_config_changed);
362 }
363 cpa = gpr_malloc(sizeof(*cpa));
364 cpa->initial_metadata = initial_metadata;
365 cpa->subchannel = subchannel;
366 cpa->on_ready = on_ready;
367 cpa->elem = elem;
368 grpc_closure_init(&cpa->closure, continue_picking, cpa);
369 grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure, 1);
370 gpr_mu_unlock(&chand->mu_config);
371 return 0;
372}
373
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800374/* Constructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700375static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
Craig Tiller577c9b22015-11-02 14:11:15 -0800376 grpc_call_element_args *args) {
Craig Tillerb2b42612015-11-20 12:02:17 -0800377 grpc_subchannel_call_holder_init(elem->call_data, cc_pick_subchannel, elem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800378}
379
380/* Destructor for call_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700381static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
382 grpc_call_element *elem) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800383 grpc_subchannel_call_holder_destroy(exec_ctx, elem->call_data);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800384}
385
386/* Constructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700387static void init_channel_elem(grpc_exec_ctx *exec_ctx,
Craig Tiller577c9b22015-11-02 14:11:15 -0800388 grpc_channel_element *elem,
389 grpc_channel_element_args *args) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800390 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800391
Craig Tillera82950e2015-09-22 12:33:20 -0700392 memset(chand, 0, sizeof(*chand));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700393
Craig Tiller577c9b22015-11-02 14:11:15 -0800394 GPR_ASSERT(args->is_last);
Craig Tillera82950e2015-09-22 12:33:20 -0700395 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800396
Craig Tillera82950e2015-09-22 12:33:20 -0700397 gpr_mu_init(&chand->mu_config);
Craig Tiller577c9b22015-11-02 14:11:15 -0800398 chand->master = args->master;
Craig Tillera82950e2015-09-22 12:33:20 -0700399 grpc_pollset_set_init(&chand->pollset_set);
400 grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
Craig Tiller98465032015-06-29 14:36:42 -0700401
Craig Tillera82950e2015-09-22 12:33:20 -0700402 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
403 "client_channel");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800404}
405
406/* Destructor for channel_data */
Craig Tillera82950e2015-09-22 12:33:20 -0700407static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
408 grpc_channel_element *elem) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800409 channel_data *chand = elem->channel_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800410
Craig Tillera82950e2015-09-22 12:33:20 -0700411 if (chand->resolver != NULL) {
412 grpc_resolver_shutdown(exec_ctx, chand->resolver);
413 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
414 }
415 if (chand->lb_policy != NULL) {
416 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
417 }
418 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
419 grpc_pollset_set_destroy(&chand->pollset_set);
420 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;
448 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
449 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) {
467 GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
468 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 Tillera82950e2015-09-22 12:33:20 -0700479void grpc_client_channel_watch_connectivity_state(
480 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
481 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700482 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700483 gpr_mu_lock(&chand->mu_config);
484 grpc_connectivity_state_notify_on_state_change(
485 exec_ctx, &chand->state_tracker, state, on_complete);
486 gpr_mu_unlock(&chand->mu_config);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700487}
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700488
Craig Tillera82950e2015-09-22 12:33:20 -0700489grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
490 grpc_channel_element *elem) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700491 channel_data *chand = elem->channel_data;
492 return &chand->pollset_set;
493}
494
Craig Tillera82950e2015-09-22 12:33:20 -0700495void grpc_client_channel_add_interested_party(grpc_exec_ctx *exec_ctx,
496 grpc_channel_element *elem,
497 grpc_pollset *pollset) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700498 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700499 grpc_pollset_set_add_pollset(exec_ctx, &chand->pollset_set, pollset);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700500}
501
Craig Tillera82950e2015-09-22 12:33:20 -0700502void grpc_client_channel_del_interested_party(grpc_exec_ctx *exec_ctx,
503 grpc_channel_element *elem,
504 grpc_pollset *pollset) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700505 channel_data *chand = elem->channel_data;
Craig Tillera82950e2015-09-22 12:33:20 -0700506 grpc_pollset_set_del_pollset(exec_ctx, &chand->pollset_set, pollset);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700507}