blob: 55bb877576f7e4f5eb9d4663edbc15b241bb8e43 [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
Mark D. Roth2137cd82016-09-14 09:04:00 -070034#include "src/core/ext/client_channel/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. Roth15195742016-10-07 09:02:28 -070045#include "src/core/ext/client_channel/lb_policy_registry.h"
Mark D. Rotheb35a1d2016-10-19 14:53:42 -070046#include "src/core/ext/client_channel/method_config.h"
Mark D. Roth2137cd82016-09-14 09:04:00 -070047#include "src/core/ext/client_channel/subchannel.h"
Craig Tiller9533d042016-03-25 17:11:06 -070048#include "src/core/lib/channel/channel_args.h"
49#include "src/core/lib/channel/connected_channel.h"
Mark D. Roth72f6da82016-09-02 13:42:38 -070050#include "src/core/lib/channel/deadline_filter.h"
Craig Tiller9533d042016-03-25 17:11:06 -070051#include "src/core/lib/iomgr/iomgr.h"
Mark D. Roth4c0fe492016-08-31 13:51:55 -070052#include "src/core/lib/iomgr/polling_entity.h"
Craig Tiller9533d042016-03-25 17:11:06 -070053#include "src/core/lib/profiling/timers.h"
54#include "src/core/lib/support/string.h"
55#include "src/core/lib/surface/channel.h"
56#include "src/core/lib/transport/connectivity_state.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070057#include "src/core/lib/transport/metadata.h"
58#include "src/core/lib/transport/metadata_batch.h"
59#include "src/core/lib/transport/static_metadata.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070060
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080061/* Client channel implementation */
62
Mark D. Roth26b7be42016-10-24 10:08:07 -070063/*************************************************************************
64 * METHOD-CONFIG TABLE
65 */
66
Mark D. Roth9d480942016-10-19 14:18:05 -070067typedef enum {
68 WAIT_FOR_READY_UNSET,
69 WAIT_FOR_READY_FALSE,
70 WAIT_FOR_READY_TRUE
71} wait_for_ready_value;
72
73typedef struct method_parameters {
74 gpr_timespec timeout;
75 wait_for_ready_value wait_for_ready;
76} method_parameters;
77
78static void *method_parameters_copy(void *value) {
79 void *new_value = gpr_malloc(sizeof(method_parameters));
80 memcpy(new_value, value, sizeof(method_parameters));
81 return new_value;
82}
83
84static int method_parameters_cmp(void *value1, void *value2) {
85 const method_parameters *v1 = value1;
86 const method_parameters *v2 = value2;
87 const int retval = gpr_time_cmp(v1->timeout, v2->timeout);
88 if (retval != 0) return retval;
89 if (v1->wait_for_ready > v2->wait_for_ready) return 1;
90 if (v1->wait_for_ready < v2->wait_for_ready) return -1;
91 return 0;
92}
93
94static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
95 gpr_free, method_parameters_copy, method_parameters_cmp};
96
97static void *method_config_convert_value(
98 const grpc_method_config *method_config) {
99 method_parameters *value = gpr_malloc(sizeof(method_parameters));
100 const gpr_timespec *timeout = grpc_method_config_get_timeout(method_config);
101 value->timeout = timeout != NULL ? *timeout : gpr_time_0(GPR_TIMESPAN);
102 const bool *wait_for_ready =
103 grpc_method_config_get_wait_for_ready(method_config);
104 value->wait_for_ready =
105 wait_for_ready == NULL
106 ? WAIT_FOR_READY_UNSET
107 : (wait_for_ready ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE);
108 return value;
109}
110
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700111/*************************************************************************
112 * CHANNEL-WIDE FUNCTIONS
113 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114
Craig Tiller800dacb2015-10-06 09:10:26 -0700115typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700116 /** resolver for this channel */
117 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700118 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700119 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700120 /** client channel factory */
121 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700122
Mark D. Roth046cf762016-09-26 11:13:51 -0700123 /** mutex protecting all variables below in this data structure */
Mark D. Rothff4df062016-08-22 15:02:49 -0700124 gpr_mu mu;
Mark D. Roth046cf762016-09-26 11:13:51 -0700125 /** currently active load balancer */
Craig Tillerf5f17122015-06-25 08:47:26 -0700126 grpc_lb_policy *lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700127 /** maps method names to method_parameters structs */
128 grpc_mdstr_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700129 /** incoming resolver result - set by resolver.next() */
130 grpc_resolver_result *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700131 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700132 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700133 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700134 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700135 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700136 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700137 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700138 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800139 /** owning stack */
140 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800141 /** interested parties (owned) */
142 grpc_pollset_set *interested_parties;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143} channel_data;
144
Craig Tillerd6c98df2015-08-18 09:33:44 -0700145/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700146 resolver, to watch for state changes from the lb_policy. When a state
147 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700148typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700149 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700150 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700151 grpc_connectivity_state state;
152 grpc_lb_policy *lb_policy;
153} lb_policy_connectivity_watcher;
154
Craig Tillera82950e2015-09-22 12:33:20 -0700155static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
156 grpc_lb_policy *lb_policy,
157 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700158
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800159static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
160 channel_data *chand,
161 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700162 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800163 const char *reason) {
164 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700165 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800166 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700167 /* cancel picks with wait_for_ready=false */
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800168 grpc_lb_policy_cancel_picks(
169 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700170 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700171 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800172 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700173 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
174 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800175}
176
Craig Tiller804ff712016-05-05 16:25:40 -0700177static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
178 lb_policy_connectivity_watcher *w,
179 grpc_error *error) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800180 grpc_connectivity_state publish_state = w->state;
Craig Tiller5795da72015-09-17 15:27:13 -0700181 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700182 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700183
Craig Tiller48ed92e2016-06-02 11:07:12 -0700184 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800185 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
186 grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
Craig Tillerf62c4d52015-12-04 07:43:07 -0800187 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
188 w->chand->lb_policy = NULL;
Craig Tillercb2609f2015-11-24 17:19:19 -0800189 }
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800190 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
Craig Tillerfc353d62016-05-10 12:58:03 -0700191 GRPC_ERROR_REF(error), "lb_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700192 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillera82950e2015-09-22 12:33:20 -0700193 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
194 }
Craig Tiller5795da72015-09-17 15:27:13 -0700195}
196
Craig Tillera82950e2015-09-22 12:33:20 -0700197static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700198 grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700199 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700200
Mark D. Rothff4df062016-08-22 15:02:49 -0700201 gpr_mu_lock(&w->chand->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700202 on_lb_policy_state_changed_locked(exec_ctx, w, error);
Mark D. Rothff4df062016-08-22 15:02:49 -0700203 gpr_mu_unlock(&w->chand->mu);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700204
Craig Tiller906e3bc2015-11-24 07:31:31 -0800205 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700206 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700207}
208
Craig Tillera82950e2015-09-22 12:33:20 -0700209static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
210 grpc_lb_policy *lb_policy,
211 grpc_connectivity_state current_state) {
212 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800213 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700214
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700215 w->chand = chand;
Craig Tillera82950e2015-09-22 12:33:20 -0700216 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700217 w->state = current_state;
218 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700219 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
220 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700221}
222
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700223static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
224 grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700225 channel_data *chand = arg;
226 grpc_lb_policy *lb_policy = NULL;
227 grpc_lb_policy *old_lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700228 grpc_mdstr_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700229 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700230 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700231 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Craig Tiller3f475422015-06-25 10:43:05 -0700232
Mark D. Roth046cf762016-09-26 11:13:51 -0700233 if (chand->resolver_result != NULL) {
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700234 grpc_lb_policy_args lb_policy_args;
Mark D. Roth933c9552016-09-21 08:12:11 -0700235 lb_policy_args.server_name =
Mark D. Roth046cf762016-09-26 11:13:51 -0700236 grpc_resolver_result_get_server_name(chand->resolver_result);
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700237 lb_policy_args.addresses =
Mark D. Roth046cf762016-09-26 11:13:51 -0700238 grpc_resolver_result_get_addresses(chand->resolver_result);
239 lb_policy_args.additional_args =
240 grpc_resolver_result_get_lb_policy_args(chand->resolver_result);
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700241 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Mark D. Roth88405f72016-10-03 08:24:52 -0700242
243 // Special case: If all of the addresses are balancer addresses,
244 // assume that we should use the grpclb policy, regardless of what the
245 // resolver actually specified.
Mark D. Roth07aab592016-10-04 10:02:00 -0700246 const char *lb_policy_name =
Mark D. Roth88405f72016-10-03 08:24:52 -0700247 grpc_resolver_result_get_lb_policy_name(chand->resolver_result);
248 bool found_backend_address = false;
249 for (size_t i = 0; i < lb_policy_args.addresses->num_addresses; ++i) {
250 if (!lb_policy_args.addresses->addresses[i].is_balancer) {
251 found_backend_address = true;
252 break;
253 }
254 }
255 if (!found_backend_address) {
256 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
257 gpr_log(GPR_INFO,
258 "resolver requested LB policy %s but provided only balancer "
259 "addresses, no backend addresses -- forcing use of grpclb LB "
Mark D. Roth07aab592016-10-04 10:02:00 -0700260 "policy",
261 (lb_policy_name == NULL ? "(none)" : lb_policy_name));
Mark D. Roth88405f72016-10-03 08:24:52 -0700262 }
263 lb_policy_name = "grpclb";
264 }
265 // Use pick_first if nothing was specified and we didn't select grpclb
266 // above.
267 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
268
269 lb_policy =
270 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700271 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700272 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700273 GRPC_ERROR_UNREF(state_error);
Craig Tiller804ff712016-05-05 16:25:40 -0700274 state =
275 grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700276 }
Mark D. Roth046cf762016-09-26 11:13:51 -0700277 const grpc_arg *channel_arg = grpc_channel_args_find(
278 lb_policy_args.additional_args, GRPC_ARG_SERVICE_CONFIG);
279 if (channel_arg != NULL) {
280 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth9d480942016-10-19 14:18:05 -0700281 method_params_table = grpc_method_config_table_convert(
282 (grpc_method_config_table *)channel_arg->value.pointer.p,
283 method_config_convert_value, &method_parameters_vtable);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700284 }
Mark D. Roth046cf762016-09-26 11:13:51 -0700285 grpc_resolver_result_unref(exec_ctx, chand->resolver_result);
286 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700287 }
288
Craig Tiller86c99582015-11-25 15:22:26 -0800289 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800290 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
291 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800292 }
293
Mark D. Rothff4df062016-08-22 15:02:49 -0700294 gpr_mu_lock(&chand->mu);
Craig Tiller3f475422015-06-25 10:43:05 -0700295 old_lb_policy = chand->lb_policy;
296 chand->lb_policy = lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700297 if (chand->method_params_table != NULL) {
298 grpc_mdstr_hash_table_unref(chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700299 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700300 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700301 if (lb_policy != NULL) {
302 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
303 NULL);
304 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700305 grpc_closure_list_fail_all(
306 &chand->waiting_for_config_closures,
307 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller6c396862016-01-28 13:53:40 -0800308 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
309 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700310 }
311 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
312 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700313 exit_idle = true;
314 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700315 }
Craig Tiller98465032015-06-29 14:36:42 -0700316
Craig Tiller804ff712016-05-05 16:25:40 -0700317 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700318 set_channel_connectivity_state_locked(
319 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700320 if (lb_policy != NULL) {
321 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700322 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800323 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth046cf762016-09-26 11:13:51 -0700324 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700325 &chand->on_resolver_result_changed);
326 gpr_mu_unlock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700327 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800328 if (chand->resolver != NULL) {
329 grpc_resolver_shutdown(exec_ctx, chand->resolver);
330 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
331 chand->resolver = NULL;
332 }
Craig Tiller804ff712016-05-05 16:25:40 -0700333 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800334 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700335 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700336 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
337 GPR_ARRAY_SIZE(refs)),
338 "resolver_gone");
Mark D. Rothff4df062016-08-22 15:02:49 -0700339 gpr_mu_unlock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700340 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700341
Craig Tillera82950e2015-09-22 12:33:20 -0700342 if (exit_idle) {
343 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
344 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
345 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700346
Craig Tillera82950e2015-09-22 12:33:20 -0700347 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800348 grpc_pollset_set_del_pollset_set(
349 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700350 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
351 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700352
Craig Tillera82950e2015-09-22 12:33:20 -0700353 if (lb_policy != NULL) {
354 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
355 }
Craig Tiller45724b32015-09-22 10:42:19 -0700356
Craig Tiller906e3bc2015-11-24 07:31:31 -0800357 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700358 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700359}
360
Craig Tillera82950e2015-09-22 12:33:20 -0700361static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
362 grpc_channel_element *elem,
363 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700364 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700365
Craig Tiller332f1b32016-05-24 13:21:21 -0700366 grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700367
Craig Tillerd7f12e32016-03-03 10:08:31 -0800368 GPR_ASSERT(op->set_accept_stream == false);
Craig Tiller28bf8912015-12-07 16:07:04 -0800369 if (op->bind_pollset != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800370 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
Craig Tillere2c62372015-12-07 16:11:03 -0800371 op->bind_pollset);
Craig Tiller28bf8912015-12-07 16:07:04 -0800372 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700373
Mark D. Rothff4df062016-08-22 15:02:49 -0700374 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700375 if (op->on_connectivity_state_change != NULL) {
376 grpc_connectivity_state_notify_on_state_change(
377 exec_ctx, &chand->state_tracker, op->connectivity_state,
378 op->on_connectivity_state_change);
379 op->on_connectivity_state_change = NULL;
380 op->connectivity_state = NULL;
381 }
382
Craig Tiller26dab312015-12-07 14:43:47 -0800383 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800384 if (chand->lb_policy == NULL) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700385 grpc_exec_ctx_sched(exec_ctx, op->send_ping,
386 GRPC_ERROR_CREATE("Ping with no load balancing"),
387 NULL);
Craig Tiller26dab312015-12-07 14:43:47 -0800388 } else {
Craig Tiller28bf8912015-12-07 16:07:04 -0800389 grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800390 op->bind_pollset = NULL;
391 }
392 op->send_ping = NULL;
393 }
394
Craig Tiller1c51edc2016-05-07 16:18:43 -0700395 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
396 if (chand->resolver != NULL) {
397 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700398 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700399 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
400 grpc_resolver_shutdown(exec_ctx, chand->resolver);
401 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
402 chand->resolver = NULL;
403 if (!chand->started_resolving) {
404 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
405 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700406 grpc_exec_ctx_enqueue_list(exec_ctx,
407 &chand->waiting_for_config_closures, NULL);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700408 }
409 if (chand->lb_policy != NULL) {
410 grpc_pollset_set_del_pollset_set(exec_ctx,
411 chand->lb_policy->interested_parties,
412 chand->interested_parties);
413 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
414 chand->lb_policy = NULL;
415 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700416 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700417 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700418 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700419 gpr_mu_unlock(&chand->mu);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700420}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800421
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700422/* Constructor for channel_data */
423static void cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
424 grpc_channel_element *elem,
425 grpc_channel_element_args *args) {
426 channel_data *chand = elem->channel_data;
427
428 memset(chand, 0, sizeof(*chand));
429
430 GPR_ASSERT(args->is_last);
431 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
432
433 gpr_mu_init(&chand->mu);
434 grpc_closure_init(&chand->on_resolver_result_changed,
435 on_resolver_result_changed, chand);
436 chand->owning_stack = args->channel_stack;
437
438 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
439 "client_channel");
440 chand->interested_parties = grpc_pollset_set_create();
441}
442
443/* Destructor for channel_data */
444static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
445 grpc_channel_element *elem) {
446 channel_data *chand = elem->channel_data;
447
448 if (chand->resolver != NULL) {
449 grpc_resolver_shutdown(exec_ctx, chand->resolver);
450 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
451 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700452 if (chand->client_channel_factory != NULL) {
453 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
454 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700455 if (chand->lb_policy != NULL) {
456 grpc_pollset_set_del_pollset_set(exec_ctx,
457 chand->lb_policy->interested_parties,
458 chand->interested_parties);
459 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
460 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700461 if (chand->method_params_table != NULL) {
462 grpc_mdstr_hash_table_unref(chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700463 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700464 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
465 grpc_pollset_set_destroy(chand->interested_parties);
466 gpr_mu_destroy(&chand->mu);
467}
468
469/*************************************************************************
470 * PER-CALL FUNCTIONS
471 */
472
473#define GET_CALL(call_data) \
474 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
475
476#define CANCELLED_CALL ((grpc_subchannel_call *)1)
477
478typedef enum {
479 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
480 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
481} subchannel_creation_phase;
482
483/** Call data. Holds a pointer to grpc_subchannel_call and the
484 associated machinery to create such a pointer.
485 Handles queueing of stream ops until a call object is ready, waiting
486 for initial metadata before trying to create a call object,
487 and handling cancellation gracefully. */
488typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700489 // State for handling deadlines.
490 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700491 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
492 // and this struct both independently store a pointer to the call
493 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700494 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700495 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700496
Mark D. Rothe40dd292016-10-05 14:58:37 -0700497 grpc_mdstr *path; // Request path.
498 gpr_timespec call_start_time;
499 gpr_timespec deadline;
Mark D. Roth9d480942016-10-19 14:18:05 -0700500 wait_for_ready_value wait_for_ready_from_service_config;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700501 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700502
Mark D. Rothf28763c2016-09-14 15:18:40 -0700503 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700504
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700505 /** either 0 for no call, 1 for cancelled, or a pointer to a
506 grpc_subchannel_call */
507 gpr_atm subchannel_call;
508
509 gpr_mu mu;
510
511 subchannel_creation_phase creation_phase;
512 grpc_connected_subchannel *connected_subchannel;
513 grpc_polling_entity *pollent;
514
Craig Tiller57726ca2016-09-12 11:59:45 -0700515 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700516 size_t waiting_ops_count;
517 size_t waiting_ops_capacity;
518
519 grpc_closure next_step;
520
521 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200522
523 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700524} call_data;
525
526static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
527 GPR_TIMER_BEGIN("add_waiting_locked", 0);
528 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
529 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
530 calld->waiting_ops =
531 gpr_realloc(calld->waiting_ops,
532 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
533 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700534 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700535 GPR_TIMER_END("add_waiting_locked", 0);
536}
537
538static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
539 grpc_error *error) {
540 size_t i;
541 for (i = 0; i < calld->waiting_ops_count; i++) {
542 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700543 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700544 }
545 calld->waiting_ops_count = 0;
546 GRPC_ERROR_UNREF(error);
547}
548
549typedef struct {
Craig Tiller57726ca2016-09-12 11:59:45 -0700550 grpc_transport_stream_op **ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700551 size_t nops;
552 grpc_subchannel_call *call;
553} retry_ops_args;
554
555static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
556 retry_ops_args *a = args;
557 size_t i;
558 for (i = 0; i < a->nops; i++) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700559 grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700560 }
561 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
562 gpr_free(a->ops);
563 gpr_free(a);
564}
565
566static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700567 if (calld->waiting_ops_count == 0) {
568 return;
569 }
570
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700571 retry_ops_args *a = gpr_malloc(sizeof(*a));
572 a->ops = calld->waiting_ops;
573 a->nops = calld->waiting_ops_count;
574 a->call = GET_CALL(calld);
575 if (a->call == CANCELLED_CALL) {
576 gpr_free(a);
577 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
578 return;
579 }
580 calld->waiting_ops = NULL;
581 calld->waiting_ops_count = 0;
582 calld->waiting_ops_capacity = 0;
583 GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
584 grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(retry_ops, a),
585 GRPC_ERROR_NONE, NULL);
586}
587
588static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
589 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700590 grpc_call_element *elem = arg;
591 call_data *calld = elem->call_data;
592 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700593 gpr_mu_lock(&calld->mu);
594 GPR_ASSERT(calld->creation_phase ==
595 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700596 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
597 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700598 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
599 if (calld->connected_subchannel == NULL) {
600 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
601 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
602 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700603 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700604 /* already cancelled before subchannel became ready */
605 fail_locked(exec_ctx, calld,
606 GRPC_ERROR_CREATE_REFERENCING(
607 "Cancelled before creating subchannel", &error, 1));
608 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700609 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700610 grpc_subchannel_call *subchannel_call = NULL;
611 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700612 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
613 calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700614 if (new_error != GRPC_ERROR_NONE) {
615 new_error = grpc_error_add_child(new_error, error);
616 subchannel_call = CANCELLED_CALL;
617 fail_locked(exec_ctx, calld, new_error);
618 }
619 gpr_atm_rel_store(&calld->subchannel_call,
620 (gpr_atm)(uintptr_t)subchannel_call);
621 retry_waiting_locked(exec_ctx, calld);
622 }
623 gpr_mu_unlock(&calld->mu);
624 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
625}
626
627static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
628 call_data *calld = elem->call_data;
629 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
630 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
631 return NULL;
632 } else {
633 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
634 }
635}
636
Craig Tiller577c9b22015-11-02 14:11:15 -0800637typedef struct {
638 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800639 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800640 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800641 grpc_closure *on_ready;
642 grpc_call_element *elem;
643 grpc_closure closure;
644} continue_picking_args;
645
Yuchen Zeng144ce652016-09-01 18:19:34 -0700646/** Return true if subchannel is available immediately (in which case on_ready
647 should not be called), or false otherwise (in which case on_ready should be
648 called when the subchannel is available). */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700649static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
650 grpc_metadata_batch *initial_metadata,
651 uint32_t initial_metadata_flags,
652 grpc_connected_subchannel **connected_subchannel,
Mark D. Roth72f6da82016-09-02 13:42:38 -0700653 grpc_closure *on_ready, grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800654
Craig Tiller804ff712016-05-05 16:25:40 -0700655static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
656 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800657 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700658 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800659 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700660 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700661 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700662 } else {
663 call_data *calld = cpa->elem->call_data;
664 gpr_mu_lock(&calld->mu);
665 if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
Mark D. Rothfd2ddd22016-10-07 10:11:10 -0700666 cpa->initial_metadata_flags, cpa->connected_subchannel,
667 cpa->on_ready, GRPC_ERROR_NONE)) {
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700668 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL);
669 }
670 gpr_mu_unlock(&calld->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800671 }
672 gpr_free(cpa);
673}
674
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700675static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
676 grpc_metadata_batch *initial_metadata,
677 uint32_t initial_metadata_flags,
678 grpc_connected_subchannel **connected_subchannel,
Mark D. Roth72f6da82016-09-02 13:42:38 -0700679 grpc_closure *on_ready, grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700680 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700681
Craig Tiller577c9b22015-11-02 14:11:15 -0800682 channel_data *chand = elem->channel_data;
683 call_data *calld = elem->call_data;
684 continue_picking_args *cpa;
685 grpc_closure *closure;
686
Craig Tillerb5585d42015-11-17 07:18:31 -0800687 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800688
Mark D. Rothff4df062016-08-22 15:02:49 -0700689 gpr_mu_lock(&chand->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800690 if (initial_metadata == NULL) {
691 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800692 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
Mark D. Roth5f844002016-09-08 08:20:53 -0700693 connected_subchannel, GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800694 }
695 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700696 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800697 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800698 if (cpa->connected_subchannel == connected_subchannel) {
699 cpa->connected_subchannel = NULL;
Mark D. Roth932b10c2016-09-09 08:44:30 -0700700 grpc_exec_ctx_sched(
701 exec_ctx, cpa->on_ready,
702 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800703 }
704 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700705 gpr_mu_unlock(&chand->mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700706 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700707 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700708 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800709 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700710 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800711 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800712 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700713 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothff4df062016-08-22 15:02:49 -0700714 gpr_mu_unlock(&chand->mu);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700715 // If the application explicitly set wait_for_ready, use that.
716 // Otherwise, if the service config specified a value for this
717 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700718 const bool wait_for_ready_set_from_api =
719 initial_metadata_flags &
720 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
721 const bool wait_for_ready_set_from_service_config =
722 calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
723 if (!wait_for_ready_set_from_api &&
724 wait_for_ready_set_from_service_config) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700725 if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
726 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
727 } else {
728 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
729 }
730 }
David Garcia Quintas61c58012016-10-03 14:44:20 -0700731 // TODO(dgq): make this deadline configurable somehow.
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700732 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700733 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
734 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Mark D. Roth55f25b62016-10-12 14:55:20 -0700735 const bool result = grpc_lb_policy_pick(
736 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700737 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
738 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700739 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800740 }
741 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700742 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800743 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth046cf762016-09-26 11:13:51 -0700744 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700745 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800746 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700747 if (chand->resolver != NULL) {
748 cpa = gpr_malloc(sizeof(*cpa));
749 cpa->initial_metadata = initial_metadata;
750 cpa->initial_metadata_flags = initial_metadata_flags;
751 cpa->connected_subchannel = connected_subchannel;
752 cpa->on_ready = on_ready;
753 cpa->elem = elem;
754 grpc_closure_init(&cpa->closure, continue_picking, cpa);
Craig Tiller804ff712016-05-05 16:25:40 -0700755 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
756 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700757 } else {
Craig Tiller332f1b32016-05-24 13:21:21 -0700758 grpc_exec_ctx_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"),
759 NULL);
Craig Tiller0eab6972016-04-23 12:59:57 -0700760 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700761 gpr_mu_unlock(&chand->mu);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700762
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700763 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700764 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800765}
766
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700767// The logic here is fairly complicated, due to (a) the fact that we
768// need to handle the case where we receive the send op before the
769// initial metadata op, and (b) the need for efficiency, especially in
770// the streaming case.
771// TODO(ctiller): Explain this more thoroughly.
772static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
773 grpc_call_element *elem,
774 grpc_transport_stream_op *op) {
775 call_data *calld = elem->call_data;
Yuchen Zeng19656b12016-09-01 18:00:45 -0700776 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700777 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Mark D. Roth72f6da82016-09-02 13:42:38 -0700778 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700779 /* try to (atomically) get the call */
780 grpc_subchannel_call *call = GET_CALL(calld);
781 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
782 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700783 grpc_transport_stream_op_finish_with_failure(
784 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700785 GPR_TIMER_END("cc_start_transport_stream_op", 0);
786 return;
787 }
788 if (call != NULL) {
789 grpc_subchannel_call_process_op(exec_ctx, call, op);
790 GPR_TIMER_END("cc_start_transport_stream_op", 0);
791 return;
792 }
793 /* we failed; lock and figure out what to do */
794 gpr_mu_lock(&calld->mu);
795retry:
796 /* need to recheck that another thread hasn't set the call */
797 call = GET_CALL(calld);
798 if (call == CANCELLED_CALL) {
799 gpr_mu_unlock(&calld->mu);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700800 grpc_transport_stream_op_finish_with_failure(
801 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700802 GPR_TIMER_END("cc_start_transport_stream_op", 0);
803 return;
804 }
805 if (call != NULL) {
806 gpr_mu_unlock(&calld->mu);
807 grpc_subchannel_call_process_op(exec_ctx, call, op);
808 GPR_TIMER_END("cc_start_transport_stream_op", 0);
809 return;
810 }
811 /* if this is a cancellation, then we can raise our cancelled flag */
812 if (op->cancel_error != GRPC_ERROR_NONE) {
813 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
814 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
815 goto retry;
816 } else {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700817 // Stash a copy of cancel_error in our call data, so that we can use
818 // it for subsequent operations. This ensures that if the call is
819 // cancelled before any ops are passed down (e.g., if the deadline
820 // is in the past when the call starts), we can return the right
821 // error to the caller when the first op does get passed down.
822 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700823 switch (calld->creation_phase) {
824 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
825 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
826 break;
827 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Mark D. Rothd4c0f552016-09-01 09:25:32 -0700828 pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel,
Mark D. Roth72f6da82016-09-02 13:42:38 -0700829 NULL, GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700830 break;
831 }
832 gpr_mu_unlock(&calld->mu);
Mark D. Roth72f6da82016-09-02 13:42:38 -0700833 grpc_transport_stream_op_finish_with_failure(
834 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700835 GPR_TIMER_END("cc_start_transport_stream_op", 0);
836 return;
837 }
838 }
839 /* if we don't have a subchannel, try to get one */
840 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
841 calld->connected_subchannel == NULL &&
842 op->send_initial_metadata != NULL) {
843 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Yuchen Zeng19656b12016-09-01 18:00:45 -0700844 grpc_closure_init(&calld->next_step, subchannel_ready, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700845 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -0700846 /* If a subchannel is not available immediately, the polling entity from
847 call_data should be provided to channel_data's interested_parties, so
848 that IO of the lb_policy and resolver could be done under it. */
Mark D. Rothd4c0f552016-09-01 09:25:32 -0700849 if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata,
Mark D. Rothe40dd292016-10-05 14:58:37 -0700850 op->send_initial_metadata_flags,
851 &calld->connected_subchannel, &calld->next_step,
852 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700853 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
854 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -0700855 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700856 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
857 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700858 }
859 }
860 /* if we've got a subchannel, then let's ask it to create a call */
861 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
862 calld->connected_subchannel != NULL) {
863 grpc_subchannel_call *subchannel_call = NULL;
864 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700865 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
866 calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700867 if (error != GRPC_ERROR_NONE) {
868 subchannel_call = CANCELLED_CALL;
869 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
870 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
871 }
872 gpr_atm_rel_store(&calld->subchannel_call,
873 (gpr_atm)(uintptr_t)subchannel_call);
874 retry_waiting_locked(exec_ctx, calld);
875 goto retry;
876 }
877 /* nothing to be done but wait */
878 add_waiting_locked(calld, op);
879 gpr_mu_unlock(&calld->mu);
880 GPR_TIMER_END("cc_start_transport_stream_op", 0);
881}
882
Mark D. Rothe40dd292016-10-05 14:58:37 -0700883// Gets data from the service config. Invoked when the resolver returns
884// its initial result.
885static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
886 grpc_error *error) {
887 grpc_call_element *elem = arg;
888 channel_data *chand = elem->channel_data;
889 call_data *calld = elem->call_data;
890 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -0700891 if (error == GRPC_ERROR_NONE) {
892 // Get the method config table from channel data.
893 gpr_mu_lock(&chand->mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700894 grpc_mdstr_hash_table *method_params_table = NULL;
895 if (chand->method_params_table != NULL) {
896 method_params_table =
897 grpc_mdstr_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700898 }
Mark D. Roth196387a2016-10-12 14:53:36 -0700899 gpr_mu_unlock(&chand->mu);
900 // If the method config table was present, use it.
Mark D. Roth9d480942016-10-19 14:18:05 -0700901 if (method_params_table != NULL) {
902 const method_parameters *method_params =
903 grpc_method_config_table_get(method_params_table, calld->path);
904 if (method_params != NULL) {
905 const bool have_method_timeout =
906 gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
907 if (have_method_timeout ||
908 method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -0700909 gpr_mu_lock(&calld->mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700910 if (have_method_timeout) {
911 const gpr_timespec per_method_deadline =
912 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Roth196387a2016-10-12 14:53:36 -0700913 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
914 calld->deadline = per_method_deadline;
915 // Reset deadline timer.
916 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
917 }
918 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700919 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -0700920 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -0700921 method_params->wait_for_ready;
Mark D. Roth196387a2016-10-12 14:53:36 -0700922 }
923 gpr_mu_unlock(&calld->mu);
924 }
925 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700926 grpc_mdstr_hash_table_unref(method_params_table);
Mark D. Roth196387a2016-10-12 14:53:36 -0700927 }
Mark D. Rothe40dd292016-10-05 14:58:37 -0700928 }
Mark D. Roth31292f22016-10-12 13:14:07 -0700929 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700930}
931
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800932/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700933static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
934 grpc_call_element *elem,
935 grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -0700936 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700937 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700938 // Initialize data members.
939 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Mark D. Rothaa850a72016-09-26 13:38:02 -0700940 calld->path = GRPC_MDSTR_REF(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -0700941 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700942 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
943 calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700944 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700945 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700946 gpr_mu_init(&calld->mu);
947 calld->connected_subchannel = NULL;
948 calld->waiting_ops = NULL;
949 calld->waiting_ops_count = 0;
950 calld->waiting_ops_capacity = 0;
951 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
952 calld->owning_call = args->call_stack;
953 calld->pollent = NULL;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700954 // If the resolver has already returned results, then we can access
955 // the service config parameters immediately. Otherwise, we need to
956 // defer that work until the resolver returns an initial result.
957 // TODO(roth): This code is almost but not quite identical to the code
958 // in read_service_config() above. It would be nice to find a way to
959 // combine them, to avoid having to maintain it twice.
960 gpr_mu_lock(&chand->mu);
961 if (chand->lb_policy != NULL) {
962 // We already have a resolver result, so check for service config.
Mark D. Roth9d480942016-10-19 14:18:05 -0700963 if (chand->method_params_table != NULL) {
964 grpc_mdstr_hash_table *method_params_table =
965 grpc_mdstr_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700966 gpr_mu_unlock(&chand->mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700967 method_parameters *method_params =
968 grpc_method_config_table_get(method_params_table, args->path);
969 if (method_params != NULL) {
970 if (gpr_time_cmp(method_params->timeout,
971 gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700972 gpr_timespec per_method_deadline =
Mark D. Roth9d480942016-10-19 14:18:05 -0700973 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700974 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
975 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700976 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700977 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -0700978 method_params->wait_for_ready;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700979 }
980 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700981 grpc_mdstr_hash_table_unref(method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700982 } else {
983 gpr_mu_unlock(&chand->mu);
984 }
985 } else {
986 // We don't yet have a resolver result, so register a callback to
987 // get the service config data once the resolver returns.
Mark D. Roth31292f22016-10-12 13:14:07 -0700988 // Take a reference to the call stack to be owned by the callback.
989 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -0700990 grpc_closure_init(&calld->read_service_config, read_service_config, elem);
991 grpc_closure_list_append(&chand->waiting_for_config_closures,
992 &calld->read_service_config, GRPC_ERROR_NONE);
993 gpr_mu_unlock(&chand->mu);
994 }
995 // Start the deadline timer with the current deadline value. If we
996 // do not yet have service config data, then the timer may be reset
997 // later.
998 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Mark D. Roth0badbe82016-06-23 10:15:12 -0700999 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001000}
1001
1002/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001003static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1004 grpc_call_element *elem,
1005 const grpc_call_final_info *final_info,
1006 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001007 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001008 grpc_deadline_state_destroy(exec_ctx, elem);
Mark D. Rothaa850a72016-09-26 13:38:02 -07001009 GRPC_MDSTR_UNREF(calld->path);
Mark D. Rothf28763c2016-09-14 15:18:40 -07001010 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001011 grpc_subchannel_call *call = GET_CALL(calld);
1012 if (call != NULL && call != CANCELLED_CALL) {
1013 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1014 }
1015 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
1016 gpr_mu_destroy(&calld->mu);
1017 GPR_ASSERT(calld->waiting_ops_count == 0);
1018 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001019 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001020}
1021
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001022static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1023 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001024 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001025 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001026 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001027}
1028
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001029/*************************************************************************
1030 * EXPORTED SYMBOLS
1031 */
1032
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001033const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001034 cc_start_transport_stream_op,
1035 cc_start_transport_op,
1036 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001037 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001038 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001039 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001040 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001041 cc_init_channel_elem,
1042 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001043 cc_get_peer,
1044 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001045};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001046
Mark D. Roth60534972016-09-20 08:37:12 -07001047void grpc_client_channel_finish_initialization(
Mark D. Roth0e48a9a2016-09-08 14:14:39 -07001048 grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
1049 grpc_resolver *resolver,
1050 grpc_client_channel_factory *client_channel_factory) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001051 /* post construction initialization: set the transport setup pointer */
Mark D. Roth7f7d1652016-09-20 10:46:15 -07001052 GPR_ASSERT(client_channel_factory != NULL);
Craig Tillera82950e2015-09-22 12:33:20 -07001053 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001054 channel_data *chand = elem->channel_data;
Mark D. Rothff4df062016-08-22 15:02:49 -07001055 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -07001056 GPR_ASSERT(!chand->resolver);
Craig Tillerf5f17122015-06-25 08:47:26 -07001057 chand->resolver = resolver;
Craig Tillera82950e2015-09-22 12:33:20 -07001058 GRPC_RESOLVER_REF(resolver, "channel");
1059 if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
1060 chand->exit_idle_when_lb_policy_arrives) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001061 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -08001062 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth046cf762016-09-26 11:13:51 -07001063 grpc_resolver_next(exec_ctx, resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -07001064 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -07001065 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -07001066 chand->client_channel_factory = client_channel_factory;
1067 grpc_client_channel_factory_ref(client_channel_factory);
Mark D. Rothff4df062016-08-22 15:02:49 -07001068 gpr_mu_unlock(&chand->mu);
Craig Tiller190d3602015-02-18 09:23:38 -08001069}
Craig Tiller48cb07c2015-07-15 16:16:15 -07001070
Craig Tillera82950e2015-09-22 12:33:20 -07001071grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1072 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001073 channel_data *chand = elem->channel_data;
1074 grpc_connectivity_state out;
Mark D. Rothff4df062016-08-22 15:02:49 -07001075 gpr_mu_lock(&chand->mu);
Craig Tiller804ff712016-05-05 16:25:40 -07001076 out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -07001077 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
1078 if (chand->lb_policy != NULL) {
1079 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
1080 } else {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001081 chand->exit_idle_when_lb_policy_arrives = true;
Craig Tillera82950e2015-09-22 12:33:20 -07001082 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller906e3bc2015-11-24 07:31:31 -08001083 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001084 chand->started_resolving = true;
Mark D. Roth046cf762016-09-26 11:13:51 -07001085 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -07001086 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -07001087 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001088 }
Craig Tillera82950e2015-09-22 12:33:20 -07001089 }
Mark D. Rothff4df062016-08-22 15:02:49 -07001090 gpr_mu_unlock(&chand->mu);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001091 return out;
1092}
1093
Craig Tiller86c99582015-11-25 15:22:26 -08001094typedef struct {
1095 channel_data *chand;
1096 grpc_pollset *pollset;
1097 grpc_closure *on_complete;
1098 grpc_closure my_closure;
1099} external_connectivity_watcher;
1100
Craig Tiller1d881fb2015-12-01 07:39:04 -08001101static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001102 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001103 external_connectivity_watcher *w = arg;
1104 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001105 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001106 w->pollset);
1107 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1108 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001109 gpr_free(w);
Craig Tiller804ff712016-05-05 16:25:40 -07001110 follow_up->cb(exec_ctx, follow_up->cb_arg, error);
Craig Tiller86c99582015-11-25 15:22:26 -08001111}
1112
Craig Tillera82950e2015-09-22 12:33:20 -07001113void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001114 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001115 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001116 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001117 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1118 w->chand = chand;
1119 w->pollset = pollset;
1120 w->on_complete = on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001121 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller86c99582015-11-25 15:22:26 -08001122 grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001123 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1124 "external_connectivity_watcher");
Mark D. Rothff4df062016-08-22 15:02:49 -07001125 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -07001126 grpc_connectivity_state_notify_on_state_change(
Craig Tiller86c99582015-11-25 15:22:26 -08001127 exec_ctx, &chand->state_tracker, state, &w->my_closure);
Mark D. Rothff4df062016-08-22 15:02:49 -07001128 gpr_mu_unlock(&chand->mu);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001129}