blob: 4b3d8951d7a1476b4b6b6953f82a9a7298119278 [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>
Mark D. Rothb2d24882016-10-27 15:44:07 -070042#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080043#include <grpc/support/sync.h>
44#include <grpc/support/useful.h>
45
Mark D. Roth15195742016-10-07 09:02:28 -070046#include "src/core/ext/client_channel/lb_policy_registry.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"
Mark D. Rothea846a02016-11-03 11:32:54 -070059#include "src/core/lib/transport/service_config.h"
Mark D. Roth9fe284e2016-09-12 11:22:27 -070060#include "src/core/lib/transport/static_metadata.h"
Craig Tiller8910ac62015-10-08 16:49:15 -070061
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080062/* Client channel implementation */
63
Mark D. Roth26b7be42016-10-24 10:08:07 -070064/*************************************************************************
65 * METHOD-CONFIG TABLE
66 */
67
Mark D. Roth9d480942016-10-19 14:18:05 -070068typedef enum {
69 WAIT_FOR_READY_UNSET,
70 WAIT_FOR_READY_FALSE,
71 WAIT_FOR_READY_TRUE
72} wait_for_ready_value;
73
74typedef struct method_parameters {
75 gpr_timespec timeout;
76 wait_for_ready_value wait_for_ready;
77} method_parameters;
78
79static void *method_parameters_copy(void *value) {
80 void *new_value = gpr_malloc(sizeof(method_parameters));
81 memcpy(new_value, value, sizeof(method_parameters));
82 return new_value;
83}
84
Mark D. Roth9d480942016-10-19 14:18:05 -070085static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
Mark D. Roth6ad80572016-11-03 08:33:17 -070086 gpr_free, method_parameters_copy};
Mark D. Roth9d480942016-10-19 14:18:05 -070087
Mark D. Rothe30baeb2016-11-03 08:16:19 -070088static void *method_parameters_create_from_json(const grpc_json *json) {
Mark D. Rothc968e602016-11-02 14:07:36 -070089 wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
Mark D. Roth47f10842016-11-03 08:45:27 -070090 gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
91 for (grpc_json *field = json->child; field != NULL; field = field->next) {
Mark D. Rothc968e602016-11-02 14:07:36 -070092 if (field->key == NULL) continue;
Mark D. Roth84c8a022016-11-10 09:39:34 -080093 if (strcmp(field->key, "waitForReady") == 0) {
Mark D. Rothc968e602016-11-02 14:07:36 -070094 if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
95 if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
96 return NULL;
97 }
Mark D. Roth47f10842016-11-03 08:45:27 -070098 wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
99 : WAIT_FOR_READY_FALSE;
Mark D. Rothc968e602016-11-02 14:07:36 -0700100 } else if (strcmp(field->key, "timeout") == 0) {
101 if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
Mark D. Roth84c8a022016-11-10 09:39:34 -0800102 if (field->type != GRPC_JSON_STRING) return NULL;
103 size_t len = strlen(field->value);
104 if (field->value[len - 1] != 's') return NULL;
Mark D. Rothc19049c2016-11-10 09:43:06 -0800105 char *buf = gpr_strdup(field->value);
Mark D. Roth84c8a022016-11-10 09:39:34 -0800106 buf[len - 1] = '\0'; // Remove trailing 's'.
Mark D. Rothc19049c2016-11-10 09:43:06 -0800107 char *decimal_point = strchr(buf, '.');
Mark D. Roth84c8a022016-11-10 09:39:34 -0800108 if (decimal_point != NULL) {
109 *decimal_point = '\0';
110 timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
111 if (timeout.tv_nsec == -1) {
112 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700113 return NULL;
114 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800115 // There should always be exactly 3, 6, or 9 fractional digits.
116 int multiplier = 1;
117 switch (strlen(decimal_point + 1)) {
118 case 9:
119 break;
120 case 6:
121 multiplier *= 1000;
122 break;
123 case 3:
124 multiplier *= 1000000;
125 break;
126 default: // Unsupported number of digits.
127 gpr_free(buf);
128 return NULL;
129 }
130 timeout.tv_nsec *= multiplier;
Mark D. Rothc968e602016-11-02 14:07:36 -0700131 }
Mark D. Roth84c8a022016-11-10 09:39:34 -0800132 timeout.tv_sec = gpr_parse_nonnegative_int(buf);
133 if (timeout.tv_sec == -1) return NULL;
134 gpr_free(buf);
Mark D. Rothc968e602016-11-02 14:07:36 -0700135 }
136 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700137 method_parameters *value = gpr_malloc(sizeof(method_parameters));
Mark D. Rothc968e602016-11-02 14:07:36 -0700138 value->timeout = timeout;
139 value->wait_for_ready = wait_for_ready;
Mark D. Roth9d480942016-10-19 14:18:05 -0700140 return value;
141}
142
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700143/*************************************************************************
144 * CHANNEL-WIDE FUNCTIONS
145 */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800146
Craig Tiller800dacb2015-10-06 09:10:26 -0700147typedef struct client_channel_channel_data {
Craig Tillerf5f17122015-06-25 08:47:26 -0700148 /** resolver for this channel */
149 grpc_resolver *resolver;
Craig Tiller20a3c352015-08-05 08:39:50 -0700150 /** have we started resolving this channel */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700151 bool started_resolving;
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700152 /** client channel factory */
153 grpc_client_channel_factory *client_channel_factory;
Craig Tillerf5f17122015-06-25 08:47:26 -0700154
Mark D. Roth046cf762016-09-26 11:13:51 -0700155 /** mutex protecting all variables below in this data structure */
Mark D. Rothff4df062016-08-22 15:02:49 -0700156 gpr_mu mu;
Mark D. Roth046cf762016-09-26 11:13:51 -0700157 /** currently active load balancer */
Mark D. Roth78afd772016-11-04 12:49:49 -0700158 char *lb_policy_name;
Craig Tillerf5f17122015-06-25 08:47:26 -0700159 grpc_lb_policy *lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800160 /** service config in JSON form */
161 char *service_config_json;
Mark D. Roth9d480942016-10-19 14:18:05 -0700162 /** maps method names to method_parameters structs */
163 grpc_mdstr_hash_table *method_params_table;
Mark D. Roth046cf762016-09-26 11:13:51 -0700164 /** incoming resolver result - set by resolver.next() */
Mark D. Rothaf842452016-10-21 15:05:15 -0700165 grpc_channel_args *resolver_result;
Craig Tiller3f475422015-06-25 10:43:05 -0700166 /** a list of closures that are all waiting for config to come in */
Craig Tillerd9ccbbf2015-09-22 09:30:00 -0700167 grpc_closure_list waiting_for_config_closures;
Craig Tiller3f475422015-06-25 10:43:05 -0700168 /** resolver callback */
Mark D. Rothff4df062016-08-22 15:02:49 -0700169 grpc_closure on_resolver_result_changed;
Craig Tiller3f475422015-06-25 10:43:05 -0700170 /** connectivity state being tracked */
Craig Tillerca3e9d32015-06-27 18:37:27 -0700171 grpc_connectivity_state_tracker state_tracker;
Craig Tiller48cb07c2015-07-15 16:16:15 -0700172 /** when an lb_policy arrives, should we try to exit idle */
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700173 bool exit_idle_when_lb_policy_arrives;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800174 /** owning stack */
175 grpc_channel_stack *owning_stack;
Craig Tiller69b093b2016-02-25 19:04:07 -0800176 /** interested parties (owned) */
177 grpc_pollset_set *interested_parties;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178} channel_data;
179
Craig Tillerd6c98df2015-08-18 09:33:44 -0700180/** We create one watcher for each new lb_policy that is returned from a
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700181 resolver, to watch for state changes from the lb_policy. When a state
182 change is seen, we update the channel, and create a new watcher. */
Craig Tillera82950e2015-09-22 12:33:20 -0700183typedef struct {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700184 channel_data *chand;
Craig Tiller33825112015-09-18 07:44:19 -0700185 grpc_closure on_changed;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700186 grpc_connectivity_state state;
187 grpc_lb_policy *lb_policy;
188} lb_policy_connectivity_watcher;
189
Craig Tillera82950e2015-09-22 12:33:20 -0700190static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
191 grpc_lb_policy *lb_policy,
192 grpc_connectivity_state current_state);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700193
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800194static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
195 channel_data *chand,
196 grpc_connectivity_state state,
Craig Tiller804ff712016-05-05 16:25:40 -0700197 grpc_error *error,
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800198 const char *reason) {
199 if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
Craig Tiller48ed92e2016-06-02 11:07:12 -0700200 state == GRPC_CHANNEL_SHUTDOWN) &&
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800201 chand->lb_policy != NULL) {
Mark D. Roth59c9f902016-09-28 13:33:21 -0700202 /* cancel picks with wait_for_ready=false */
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800203 grpc_lb_policy_cancel_picks(
204 exec_ctx, chand->lb_policy,
Mark D. Roth59c9f902016-09-28 13:33:21 -0700205 /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
Mark D. Roth58f52b72016-09-09 13:55:18 -0700206 /* check= */ 0, GRPC_ERROR_REF(error));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800207 }
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700208 grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
209 reason);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800210}
211
Craig Tiller804ff712016-05-05 16:25:40 -0700212static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
213 lb_policy_connectivity_watcher *w,
214 grpc_error *error) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800215 grpc_connectivity_state publish_state = w->state;
Craig Tiller5795da72015-09-17 15:27:13 -0700216 /* check if the notification is for a stale policy */
Craig Tillera82950e2015-09-22 12:33:20 -0700217 if (w->lb_policy != w->chand->lb_policy) return;
Craig Tiller5795da72015-09-17 15:27:13 -0700218
Craig Tiller48ed92e2016-06-02 11:07:12 -0700219 if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800220 publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
221 grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
Craig Tillerf62c4d52015-12-04 07:43:07 -0800222 GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
223 w->chand->lb_policy = NULL;
Craig Tillercb2609f2015-11-24 17:19:19 -0800224 }
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800225 set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
Craig Tillerfc353d62016-05-10 12:58:03 -0700226 GRPC_ERROR_REF(error), "lb_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700227 if (w->state != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillera82950e2015-09-22 12:33:20 -0700228 watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
229 }
Craig Tiller5795da72015-09-17 15:27:13 -0700230}
231
Craig Tillera82950e2015-09-22 12:33:20 -0700232static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700233 grpc_error *error) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700234 lb_policy_connectivity_watcher *w = arg;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700235
Mark D. Rothff4df062016-08-22 15:02:49 -0700236 gpr_mu_lock(&w->chand->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700237 on_lb_policy_state_changed_locked(exec_ctx, w, error);
Mark D. Rothff4df062016-08-22 15:02:49 -0700238 gpr_mu_unlock(&w->chand->mu);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700239
Craig Tiller906e3bc2015-11-24 07:31:31 -0800240 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
Craig Tillera82950e2015-09-22 12:33:20 -0700241 gpr_free(w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700242}
243
Craig Tillera82950e2015-09-22 12:33:20 -0700244static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
245 grpc_lb_policy *lb_policy,
246 grpc_connectivity_state current_state) {
247 lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
Craig Tiller906e3bc2015-11-24 07:31:31 -0800248 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700249
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700250 w->chand = chand;
Craig Tillera82950e2015-09-22 12:33:20 -0700251 grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700252 w->state = current_state;
253 w->lb_policy = lb_policy;
Craig Tillera82950e2015-09-22 12:33:20 -0700254 grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
255 &w->on_changed);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700256}
257
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700258static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
259 grpc_error *error) {
Craig Tiller3f475422015-06-25 10:43:05 -0700260 channel_data *chand = arg;
Mark D. Rothb2d24882016-10-27 15:44:07 -0700261 char *lb_policy_name = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700262 grpc_lb_policy *lb_policy = NULL;
263 grpc_lb_policy *old_lb_policy;
Mark D. Roth9d480942016-10-19 14:18:05 -0700264 grpc_mdstr_hash_table *method_params_table = NULL;
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700265 grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700266 bool exit_idle = false;
Craig Tiller804ff712016-05-05 16:25:40 -0700267 grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800268 char *service_config_json = NULL;
Craig Tiller3f475422015-06-25 10:43:05 -0700269
Mark D. Roth046cf762016-09-26 11:13:51 -0700270 if (chand->resolver_result != NULL) {
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700271 // Find LB policy name.
Mark D. Rothaf842452016-10-21 15:05:15 -0700272 const grpc_arg *channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700273 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
Mark D. Rothaf842452016-10-21 15:05:15 -0700274 if (channel_arg != NULL) {
275 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
276 lb_policy_name = channel_arg->value.string;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700277 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700278 // Special case: If all of the addresses are balancer addresses,
279 // assume that we should use the grpclb policy, regardless of what the
280 // resolver actually specified.
Mark D. Rothaf842452016-10-21 15:05:15 -0700281 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700282 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
Mark D. Rothaf842452016-10-21 15:05:15 -0700283 if (channel_arg != NULL) {
284 GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700285 grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
Mark D. Rothaf842452016-10-21 15:05:15 -0700286 bool found_backend_address = false;
287 for (size_t i = 0; i < addresses->num_addresses; ++i) {
288 if (!addresses->addresses[i].is_balancer) {
289 found_backend_address = true;
290 break;
291 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700292 }
Mark D. Rothaf842452016-10-21 15:05:15 -0700293 if (!found_backend_address) {
294 if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
295 gpr_log(GPR_INFO,
296 "resolver requested LB policy %s but provided only balancer "
297 "addresses, no backend addresses -- forcing use of grpclb LB "
298 "policy",
Mark D. Roth5f40e5d2016-10-24 13:09:05 -0700299 lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700300 }
301 lb_policy_name = "grpclb";
Mark D. Roth88405f72016-10-03 08:24:52 -0700302 }
Mark D. Roth88405f72016-10-03 08:24:52 -0700303 }
304 // Use pick_first if nothing was specified and we didn't select grpclb
305 // above.
306 if (lb_policy_name == NULL) lb_policy_name = "pick_first";
Mark D. Roth41124992016-11-03 11:22:20 -0700307 // Instantiate LB policy.
308 grpc_lb_policy_args lb_policy_args;
309 lb_policy_args.args = chand->resolver_result;
310 lb_policy_args.client_channel_factory = chand->client_channel_factory;
Mark D. Roth88405f72016-10-03 08:24:52 -0700311 lb_policy =
312 grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
Craig Tillera82950e2015-09-22 12:33:20 -0700313 if (lb_policy != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -0700314 GRPC_LB_POLICY_REF(lb_policy, "config_change");
Craig Tillerf707d622016-05-06 14:26:12 -0700315 GRPC_ERROR_UNREF(state_error);
Craig Tiller804ff712016-05-05 16:25:40 -0700316 state =
317 grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
Craig Tiller45724b32015-09-22 10:42:19 -0700318 }
Mark D. Roth41124992016-11-03 11:22:20 -0700319 // Find service config.
Mark D. Rothaf842452016-10-21 15:05:15 -0700320 channel_arg =
Mark D. Roth41124992016-11-03 11:22:20 -0700321 grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
Mark D. Roth046cf762016-09-26 11:13:51 -0700322 if (channel_arg != NULL) {
Mark D. Roth9ec28af2016-11-03 12:32:39 -0700323 GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800324 service_config_json = gpr_strdup(channel_arg->value.string);
Mark D. Roth70a1abd2016-11-04 09:26:37 -0700325 grpc_service_config *service_config =
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800326 grpc_service_config_create(service_config_json);
Mark D. Rothbdc58b22016-11-04 09:25:57 -0700327 if (service_config != NULL) {
328 method_params_table = grpc_service_config_create_method_config_table(
329 service_config, method_parameters_create_from_json,
330 &method_parameters_vtable);
331 grpc_service_config_destroy(service_config);
332 }
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700333 }
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700334 // Before we clean up, save a copy of lb_policy_name, since it might
335 // be pointing to data inside chand->resolver_result.
336 // The copy will be saved in chand->lb_policy_name below.
337 lb_policy_name = gpr_strdup(lb_policy_name);
Mark D. Rothaf842452016-10-21 15:05:15 -0700338 grpc_channel_args_destroy(chand->resolver_result);
Mark D. Roth046cf762016-09-26 11:13:51 -0700339 chand->resolver_result = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700340 }
341
Craig Tiller86c99582015-11-25 15:22:26 -0800342 if (lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800343 grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
344 chand->interested_parties);
Craig Tiller86c99582015-11-25 15:22:26 -0800345 }
346
Mark D. Rothff4df062016-08-22 15:02:49 -0700347 gpr_mu_lock(&chand->mu);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700348 if (lb_policy_name != NULL) {
349 gpr_free(chand->lb_policy_name);
350 chand->lb_policy_name = lb_policy_name;
351 }
Craig Tiller3f475422015-06-25 10:43:05 -0700352 old_lb_policy = chand->lb_policy;
353 chand->lb_policy = lb_policy;
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800354 if (service_config_json != NULL) {
355 gpr_free(chand->service_config_json);
356 chand->service_config_json = service_config_json;
357 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700358 if (chand->method_params_table != NULL) {
359 grpc_mdstr_hash_table_unref(chand->method_params_table);
Mark D. Roth046cf762016-09-26 11:13:51 -0700360 }
Mark D. Roth9d480942016-10-19 14:18:05 -0700361 chand->method_params_table = method_params_table;
Craig Tiller0ede5452016-04-23 12:21:45 -0700362 if (lb_policy != NULL) {
363 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
364 NULL);
365 } else if (chand->resolver == NULL /* disconnected */) {
Craig Tiller804ff712016-05-05 16:25:40 -0700366 grpc_closure_list_fail_all(
367 &chand->waiting_for_config_closures,
368 GRPC_ERROR_CREATE_REFERENCING("Channel disconnected", &error, 1));
Craig Tiller6c396862016-01-28 13:53:40 -0800369 grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
370 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700371 }
372 if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
373 GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700374 exit_idle = true;
375 chand->exit_idle_when_lb_policy_arrives = false;
Craig Tillera82950e2015-09-22 12:33:20 -0700376 }
Craig Tiller98465032015-06-29 14:36:42 -0700377
Craig Tiller804ff712016-05-05 16:25:40 -0700378 if (error == GRPC_ERROR_NONE && chand->resolver) {
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700379 set_channel_connectivity_state_locked(
380 exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
Craig Tillera82950e2015-09-22 12:33:20 -0700381 if (lb_policy != NULL) {
382 watch_lb_policy(exec_ctx, chand, lb_policy, state);
Craig Tiller45724b32015-09-22 10:42:19 -0700383 }
Craig Tiller906e3bc2015-11-24 07:31:31 -0800384 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth046cf762016-09-26 11:13:51 -0700385 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700386 &chand->on_resolver_result_changed);
387 gpr_mu_unlock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700388 } else {
Craig Tiller76a5c0e2016-03-09 09:05:30 -0800389 if (chand->resolver != NULL) {
390 grpc_resolver_shutdown(exec_ctx, chand->resolver);
391 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
392 chand->resolver = NULL;
393 }
Craig Tiller804ff712016-05-05 16:25:40 -0700394 grpc_error *refs[] = {error, state_error};
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800395 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700396 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700397 GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
398 GPR_ARRAY_SIZE(refs)),
399 "resolver_gone");
Mark D. Rothff4df062016-08-22 15:02:49 -0700400 gpr_mu_unlock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700401 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700402
Craig Tillera82950e2015-09-22 12:33:20 -0700403 if (exit_idle) {
404 grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
405 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
406 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700407
Craig Tillera82950e2015-09-22 12:33:20 -0700408 if (old_lb_policy != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800409 grpc_pollset_set_del_pollset_set(
410 exec_ctx, old_lb_policy->interested_parties, chand->interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700411 GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
412 }
Craig Tiller000cd8f2015-09-18 07:20:29 -0700413
Craig Tillera82950e2015-09-22 12:33:20 -0700414 if (lb_policy != NULL) {
415 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
416 }
Craig Tiller45724b32015-09-22 10:42:19 -0700417
Craig Tiller906e3bc2015-11-24 07:31:31 -0800418 GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "resolver");
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700419 GRPC_ERROR_UNREF(state_error);
Craig Tiller3f475422015-06-25 10:43:05 -0700420}
421
Craig Tillera82950e2015-09-22 12:33:20 -0700422static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
423 grpc_channel_element *elem,
424 grpc_transport_op *op) {
Craig Tillerca3e9d32015-06-27 18:37:27 -0700425 channel_data *chand = elem->channel_data;
Craig Tiller000cd8f2015-09-18 07:20:29 -0700426
Craig Tiller332f1b32016-05-24 13:21:21 -0700427 grpc_exec_ctx_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE, NULL);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700428
Craig Tillerd7f12e32016-03-03 10:08:31 -0800429 GPR_ASSERT(op->set_accept_stream == false);
Craig Tiller28bf8912015-12-07 16:07:04 -0800430 if (op->bind_pollset != NULL) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800431 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
Craig Tillere2c62372015-12-07 16:11:03 -0800432 op->bind_pollset);
Craig Tiller28bf8912015-12-07 16:07:04 -0800433 }
Craig Tillerca3e9d32015-06-27 18:37:27 -0700434
Mark D. Rothff4df062016-08-22 15:02:49 -0700435 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700436 if (op->on_connectivity_state_change != NULL) {
437 grpc_connectivity_state_notify_on_state_change(
438 exec_ctx, &chand->state_tracker, op->connectivity_state,
439 op->on_connectivity_state_change);
440 op->on_connectivity_state_change = NULL;
441 op->connectivity_state = NULL;
442 }
443
Craig Tiller26dab312015-12-07 14:43:47 -0800444 if (op->send_ping != NULL) {
Craig Tiller87b71e22015-12-07 15:14:14 -0800445 if (chand->lb_policy == NULL) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700446 grpc_exec_ctx_sched(exec_ctx, op->send_ping,
447 GRPC_ERROR_CREATE("Ping with no load balancing"),
448 NULL);
Craig Tiller26dab312015-12-07 14:43:47 -0800449 } else {
Craig Tiller28bf8912015-12-07 16:07:04 -0800450 grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
Craig Tiller26dab312015-12-07 14:43:47 -0800451 op->bind_pollset = NULL;
452 }
453 op->send_ping = NULL;
454 }
455
Craig Tiller1c51edc2016-05-07 16:18:43 -0700456 if (op->disconnect_with_error != GRPC_ERROR_NONE) {
457 if (chand->resolver != NULL) {
458 set_channel_connectivity_state_locked(
Craig Tillerd925c932016-06-06 08:38:50 -0700459 exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller1c51edc2016-05-07 16:18:43 -0700460 GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
461 grpc_resolver_shutdown(exec_ctx, chand->resolver);
462 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
463 chand->resolver = NULL;
464 if (!chand->started_resolving) {
465 grpc_closure_list_fail_all(&chand->waiting_for_config_closures,
466 GRPC_ERROR_REF(op->disconnect_with_error));
Craig Tiller9ccf5f12016-05-07 21:41:01 -0700467 grpc_exec_ctx_enqueue_list(exec_ctx,
468 &chand->waiting_for_config_closures, NULL);
Craig Tiller1c51edc2016-05-07 16:18:43 -0700469 }
470 if (chand->lb_policy != NULL) {
471 grpc_pollset_set_del_pollset_set(exec_ctx,
472 chand->lb_policy->interested_parties,
473 chand->interested_parties);
474 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
475 chand->lb_policy = NULL;
476 }
Craig Tillerb12d22a2016-04-23 12:50:21 -0700477 }
Craig Tiller1c51edc2016-05-07 16:18:43 -0700478 GRPC_ERROR_UNREF(op->disconnect_with_error);
Craig Tillera82950e2015-09-22 12:33:20 -0700479 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700480 gpr_mu_unlock(&chand->mu);
Craig Tillerca3e9d32015-06-27 18:37:27 -0700481}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800482
Mark D. Rothb2d24882016-10-27 15:44:07 -0700483static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
484 grpc_channel_element *elem,
Mark D. Rothf79ce7d2016-11-04 08:43:36 -0700485 const grpc_channel_info *info) {
Mark D. Rothb2d24882016-10-27 15:44:07 -0700486 channel_data *chand = elem->channel_data;
487 gpr_mu_lock(&chand->mu);
488 if (info->lb_policy_name != NULL) {
489 *info->lb_policy_name = chand->lb_policy_name == NULL
Mark D. Roth78afd772016-11-04 12:49:49 -0700490 ? NULL
491 : gpr_strdup(chand->lb_policy_name);
Mark D. Rothb2d24882016-10-27 15:44:07 -0700492 }
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800493 if (info->service_config_json != NULL) {
494 *info->service_config_json = chand->service_config_json == NULL
495 ? NULL
496 : gpr_strdup(chand->service_config_json);
497 }
Mark D. Rothb2d24882016-10-27 15:44:07 -0700498 gpr_mu_unlock(&chand->mu);
499}
500
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700501/* Constructor for channel_data */
502static void cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
503 grpc_channel_element *elem,
504 grpc_channel_element_args *args) {
505 channel_data *chand = elem->channel_data;
506
507 memset(chand, 0, sizeof(*chand));
508
509 GPR_ASSERT(args->is_last);
510 GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
511
512 gpr_mu_init(&chand->mu);
513 grpc_closure_init(&chand->on_resolver_result_changed,
514 on_resolver_result_changed, chand);
515 chand->owning_stack = args->channel_stack;
516
517 grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
518 "client_channel");
519 chand->interested_parties = grpc_pollset_set_create();
520}
521
522/* Destructor for channel_data */
523static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
524 grpc_channel_element *elem) {
525 channel_data *chand = elem->channel_data;
526
527 if (chand->resolver != NULL) {
528 grpc_resolver_shutdown(exec_ctx, chand->resolver);
529 GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
530 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -0700531 if (chand->client_channel_factory != NULL) {
532 grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
533 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700534 if (chand->lb_policy != NULL) {
535 grpc_pollset_set_del_pollset_set(exec_ctx,
536 chand->lb_policy->interested_parties,
537 chand->interested_parties);
538 GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
539 }
Mark D. Rothb2d24882016-10-27 15:44:07 -0700540 gpr_free(chand->lb_policy_name);
Mark D. Rothc625c7a2016-11-09 14:12:37 -0800541 gpr_free(chand->service_config_json);
Mark D. Roth9d480942016-10-19 14:18:05 -0700542 if (chand->method_params_table != NULL) {
543 grpc_mdstr_hash_table_unref(chand->method_params_table);
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700544 }
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700545 grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
546 grpc_pollset_set_destroy(chand->interested_parties);
547 gpr_mu_destroy(&chand->mu);
548}
549
550/*************************************************************************
551 * PER-CALL FUNCTIONS
552 */
553
554#define GET_CALL(call_data) \
555 ((grpc_subchannel_call *)(gpr_atm_acq_load(&(call_data)->subchannel_call)))
556
557#define CANCELLED_CALL ((grpc_subchannel_call *)1)
558
559typedef enum {
560 GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING,
561 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
562} subchannel_creation_phase;
563
564/** Call data. Holds a pointer to grpc_subchannel_call and the
565 associated machinery to create such a pointer.
566 Handles queueing of stream ops until a call object is ready, waiting
567 for initial metadata before trying to create a call object,
568 and handling cancellation gracefully. */
569typedef struct client_channel_call_data {
Mark D. Roth72f6da82016-09-02 13:42:38 -0700570 // State for handling deadlines.
571 // The code in deadline_filter.c requires this to be the first field.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700572 // TODO(roth): This is slightly sub-optimal in that grpc_deadline_state
573 // and this struct both independently store a pointer to the call
574 // stack and each has its own mutex. If/when we have time, find a way
Mark D. Roth6ad99172016-09-09 07:52:48 -0700575 // to avoid this without breaking the grpc_deadline_state abstraction.
Mark D. Roth72f6da82016-09-02 13:42:38 -0700576 grpc_deadline_state deadline_state;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700577
Mark D. Rothe40dd292016-10-05 14:58:37 -0700578 grpc_mdstr *path; // Request path.
579 gpr_timespec call_start_time;
580 gpr_timespec deadline;
Mark D. Roth9d480942016-10-19 14:18:05 -0700581 wait_for_ready_value wait_for_ready_from_service_config;
Mark D. Rothe40dd292016-10-05 14:58:37 -0700582 grpc_closure read_service_config;
Mark D. Rothaa850a72016-09-26 13:38:02 -0700583
Mark D. Rothf28763c2016-09-14 15:18:40 -0700584 grpc_error *cancel_error;
Mark D. Roth72f6da82016-09-02 13:42:38 -0700585
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700586 /** either 0 for no call, 1 for cancelled, or a pointer to a
587 grpc_subchannel_call */
588 gpr_atm subchannel_call;
589
590 gpr_mu mu;
591
592 subchannel_creation_phase creation_phase;
593 grpc_connected_subchannel *connected_subchannel;
594 grpc_polling_entity *pollent;
595
Craig Tiller57726ca2016-09-12 11:59:45 -0700596 grpc_transport_stream_op **waiting_ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700597 size_t waiting_ops_count;
598 size_t waiting_ops_capacity;
599
600 grpc_closure next_step;
601
602 grpc_call_stack *owning_call;
David Garcia Quintasd1a47f12016-09-02 12:46:44 +0200603
604 grpc_linked_mdelem lb_token_mdelem;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700605} call_data;
606
607static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
608 GPR_TIMER_BEGIN("add_waiting_locked", 0);
609 if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
610 calld->waiting_ops_capacity = GPR_MAX(3, 2 * calld->waiting_ops_capacity);
611 calld->waiting_ops =
612 gpr_realloc(calld->waiting_ops,
613 calld->waiting_ops_capacity * sizeof(*calld->waiting_ops));
614 }
Craig Tiller57726ca2016-09-12 11:59:45 -0700615 calld->waiting_ops[calld->waiting_ops_count++] = op;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700616 GPR_TIMER_END("add_waiting_locked", 0);
617}
618
619static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
620 grpc_error *error) {
621 size_t i;
622 for (i = 0; i < calld->waiting_ops_count; i++) {
623 grpc_transport_stream_op_finish_with_failure(
Craig Tiller57726ca2016-09-12 11:59:45 -0700624 exec_ctx, calld->waiting_ops[i], GRPC_ERROR_REF(error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700625 }
626 calld->waiting_ops_count = 0;
627 GRPC_ERROR_UNREF(error);
628}
629
630typedef struct {
Craig Tiller57726ca2016-09-12 11:59:45 -0700631 grpc_transport_stream_op **ops;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700632 size_t nops;
633 grpc_subchannel_call *call;
634} retry_ops_args;
635
636static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
637 retry_ops_args *a = args;
638 size_t i;
639 for (i = 0; i < a->nops; i++) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700640 grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700641 }
642 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
643 gpr_free(a->ops);
644 gpr_free(a);
645}
646
647static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
Craig Tiller57726ca2016-09-12 11:59:45 -0700648 if (calld->waiting_ops_count == 0) {
649 return;
650 }
651
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700652 retry_ops_args *a = gpr_malloc(sizeof(*a));
653 a->ops = calld->waiting_ops;
654 a->nops = calld->waiting_ops_count;
655 a->call = GET_CALL(calld);
656 if (a->call == CANCELLED_CALL) {
657 gpr_free(a);
658 fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
659 return;
660 }
661 calld->waiting_ops = NULL;
662 calld->waiting_ops_count = 0;
663 calld->waiting_ops_capacity = 0;
664 GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
665 grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(retry_ops, a),
666 GRPC_ERROR_NONE, NULL);
667}
668
669static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
670 grpc_error *error) {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700671 grpc_call_element *elem = arg;
672 call_data *calld = elem->call_data;
673 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700674 gpr_mu_lock(&calld->mu);
675 GPR_ASSERT(calld->creation_phase ==
676 GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
Yuchen Zeng19656b12016-09-01 18:00:45 -0700677 grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
678 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700679 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
680 if (calld->connected_subchannel == NULL) {
681 gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
682 fail_locked(exec_ctx, calld, GRPC_ERROR_CREATE_REFERENCING(
683 "Failed to create subchannel", &error, 1));
Mark D. Roth72f6da82016-09-02 13:42:38 -0700684 } else if (GET_CALL(calld) == CANCELLED_CALL) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700685 /* already cancelled before subchannel became ready */
David Garcia Quintas94601662016-12-09 13:58:24 -0800686 grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
687 "Cancelled before creating subchannel", &error, 1);
688 /* if due to deadline, attach the deadline exceeded status to the error */
689 if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
690 cancellation_error =
691 grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
692 GRPC_STATUS_DEADLINE_EXCEEDED);
693 }
694 fail_locked(exec_ctx, calld, cancellation_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700695 } else {
Mark D. Roth9fe284e2016-09-12 11:22:27 -0700696 /* Create call on subchannel. */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700697 grpc_subchannel_call *subchannel_call = NULL;
698 grpc_error *new_error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700699 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800700 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700701 if (new_error != GRPC_ERROR_NONE) {
702 new_error = grpc_error_add_child(new_error, error);
703 subchannel_call = CANCELLED_CALL;
704 fail_locked(exec_ctx, calld, new_error);
705 }
706 gpr_atm_rel_store(&calld->subchannel_call,
707 (gpr_atm)(uintptr_t)subchannel_call);
708 retry_waiting_locked(exec_ctx, calld);
709 }
710 gpr_mu_unlock(&calld->mu);
711 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
712}
713
714static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
715 call_data *calld = elem->call_data;
716 grpc_subchannel_call *subchannel_call = GET_CALL(calld);
717 if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
718 return NULL;
719 } else {
720 return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
721 }
722}
723
Craig Tiller577c9b22015-11-02 14:11:15 -0800724typedef struct {
725 grpc_metadata_batch *initial_metadata;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800726 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -0800727 grpc_connected_subchannel **connected_subchannel;
Craig Tiller577c9b22015-11-02 14:11:15 -0800728 grpc_closure *on_ready;
729 grpc_call_element *elem;
730 grpc_closure closure;
731} continue_picking_args;
732
Yuchen Zeng144ce652016-09-01 18:19:34 -0700733/** Return true if subchannel is available immediately (in which case on_ready
734 should not be called), or false otherwise (in which case on_ready should be
735 called when the subchannel is available). */
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700736static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
737 grpc_metadata_batch *initial_metadata,
738 uint32_t initial_metadata_flags,
739 grpc_connected_subchannel **connected_subchannel,
Mark D. Roth72f6da82016-09-02 13:42:38 -0700740 grpc_closure *on_ready, grpc_error *error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800741
Craig Tiller804ff712016-05-05 16:25:40 -0700742static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
743 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800744 continue_picking_args *cpa = arg;
Craig Tiller0ede5452016-04-23 12:21:45 -0700745 if (cpa->connected_subchannel == NULL) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800746 /* cancelled, do nothing */
Craig Tiller804ff712016-05-05 16:25:40 -0700747 } else if (error != GRPC_ERROR_NONE) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700748 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error), NULL);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700749 } else {
750 call_data *calld = cpa->elem->call_data;
751 gpr_mu_lock(&calld->mu);
752 if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
Mark D. Rothfd2ddd22016-10-07 10:11:10 -0700753 cpa->initial_metadata_flags, cpa->connected_subchannel,
754 cpa->on_ready, GRPC_ERROR_NONE)) {
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700755 grpc_exec_ctx_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE, NULL);
756 }
757 gpr_mu_unlock(&calld->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800758 }
759 gpr_free(cpa);
760}
761
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700762static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
763 grpc_metadata_batch *initial_metadata,
764 uint32_t initial_metadata_flags,
765 grpc_connected_subchannel **connected_subchannel,
Mark D. Roth72f6da82016-09-02 13:42:38 -0700766 grpc_closure *on_ready, grpc_error *error) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700767 GPR_TIMER_BEGIN("pick_subchannel", 0);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700768
Craig Tiller577c9b22015-11-02 14:11:15 -0800769 channel_data *chand = elem->channel_data;
770 call_data *calld = elem->call_data;
771 continue_picking_args *cpa;
772 grpc_closure *closure;
773
Craig Tillerb5585d42015-11-17 07:18:31 -0800774 GPR_ASSERT(connected_subchannel);
Craig Tiller577c9b22015-11-02 14:11:15 -0800775
Mark D. Rothff4df062016-08-22 15:02:49 -0700776 gpr_mu_lock(&chand->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800777 if (initial_metadata == NULL) {
778 if (chand->lb_policy != NULL) {
Craig Tillerab33b482015-11-21 08:11:04 -0800779 grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
Mark D. Roth5f844002016-09-08 08:20:53 -0700780 connected_subchannel, GRPC_ERROR_REF(error));
Craig Tiller577c9b22015-11-02 14:11:15 -0800781 }
782 for (closure = chand->waiting_for_config_closures.head; closure != NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700783 closure = closure->next_data.next) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800784 cpa = closure->cb_arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800785 if (cpa->connected_subchannel == connected_subchannel) {
786 cpa->connected_subchannel = NULL;
Mark D. Roth932b10c2016-09-09 08:44:30 -0700787 grpc_exec_ctx_sched(
788 exec_ctx, cpa->on_ready,
789 GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800790 }
791 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700792 gpr_mu_unlock(&chand->mu);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700793 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth697a1f62016-09-07 13:35:07 -0700794 GRPC_ERROR_UNREF(error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700795 return true;
Craig Tiller577c9b22015-11-02 14:11:15 -0800796 }
Mark D. Roth697a1f62016-09-07 13:35:07 -0700797 GPR_ASSERT(error == GRPC_ERROR_NONE);
Craig Tiller577c9b22015-11-02 14:11:15 -0800798 if (chand->lb_policy != NULL) {
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800799 grpc_lb_policy *lb_policy = chand->lb_policy;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700800 GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
Mark D. Rothff4df062016-08-22 15:02:49 -0700801 gpr_mu_unlock(&chand->mu);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700802 // If the application explicitly set wait_for_ready, use that.
803 // Otherwise, if the service config specified a value for this
804 // method, use that.
Mark D. Rothc1c38582016-10-11 11:03:27 -0700805 const bool wait_for_ready_set_from_api =
806 initial_metadata_flags &
807 GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
808 const bool wait_for_ready_set_from_service_config =
809 calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
810 if (!wait_for_ready_set_from_api &&
811 wait_for_ready_set_from_service_config) {
Mark D. Rothe40dd292016-10-05 14:58:37 -0700812 if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
813 initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
814 } else {
815 initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
816 }
817 }
David Garcia Quintas92eb6b92016-09-30 14:07:39 -0700818 const grpc_lb_policy_pick_args inputs = {
Yuchen Zengac8bc422016-10-05 14:00:02 -0700819 initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
820 gpr_inf_future(GPR_CLOCK_MONOTONIC)};
Mark D. Roth55f25b62016-10-12 14:55:20 -0700821 const bool result = grpc_lb_policy_pick(
822 exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700823 GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
824 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth9dab7d52016-10-07 07:48:03 -0700825 return result;
Craig Tiller577c9b22015-11-02 14:11:15 -0800826 }
827 if (chand->resolver != NULL && !chand->started_resolving) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700828 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -0800829 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth046cf762016-09-26 11:13:51 -0700830 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -0700831 &chand->on_resolver_result_changed);
Craig Tiller577c9b22015-11-02 14:11:15 -0800832 }
Craig Tiller0eab6972016-04-23 12:59:57 -0700833 if (chand->resolver != NULL) {
834 cpa = gpr_malloc(sizeof(*cpa));
835 cpa->initial_metadata = initial_metadata;
836 cpa->initial_metadata_flags = initial_metadata_flags;
837 cpa->connected_subchannel = connected_subchannel;
838 cpa->on_ready = on_ready;
839 cpa->elem = elem;
840 grpc_closure_init(&cpa->closure, continue_picking, cpa);
Craig Tiller804ff712016-05-05 16:25:40 -0700841 grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
842 GRPC_ERROR_NONE);
Craig Tiller0eab6972016-04-23 12:59:57 -0700843 } else {
Craig Tiller332f1b32016-05-24 13:21:21 -0700844 grpc_exec_ctx_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"),
845 NULL);
Craig Tiller0eab6972016-04-23 12:59:57 -0700846 }
Mark D. Rothff4df062016-08-22 15:02:49 -0700847 gpr_mu_unlock(&chand->mu);
Craig Tillerbfc9adc2016-06-27 13:16:22 -0700848
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700849 GPR_TIMER_END("pick_subchannel", 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -0700850 return false;
Craig Tiller577c9b22015-11-02 14:11:15 -0800851}
852
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700853// The logic here is fairly complicated, due to (a) the fact that we
854// need to handle the case where we receive the send op before the
855// initial metadata op, and (b) the need for efficiency, especially in
856// the streaming case.
857// TODO(ctiller): Explain this more thoroughly.
858static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
859 grpc_call_element *elem,
860 grpc_transport_stream_op *op) {
861 call_data *calld = elem->call_data;
Yuchen Zeng19656b12016-09-01 18:00:45 -0700862 channel_data *chand = elem->channel_data;
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700863 GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
Mark D. Roth72f6da82016-09-02 13:42:38 -0700864 grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700865 /* try to (atomically) get the call */
866 grpc_subchannel_call *call = GET_CALL(calld);
867 GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
868 if (call == CANCELLED_CALL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700869 grpc_transport_stream_op_finish_with_failure(
870 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700871 GPR_TIMER_END("cc_start_transport_stream_op", 0);
872 return;
873 }
874 if (call != NULL) {
875 grpc_subchannel_call_process_op(exec_ctx, call, op);
876 GPR_TIMER_END("cc_start_transport_stream_op", 0);
877 return;
878 }
879 /* we failed; lock and figure out what to do */
880 gpr_mu_lock(&calld->mu);
881retry:
882 /* need to recheck that another thread hasn't set the call */
883 call = GET_CALL(calld);
884 if (call == CANCELLED_CALL) {
885 gpr_mu_unlock(&calld->mu);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700886 grpc_transport_stream_op_finish_with_failure(
887 exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700888 GPR_TIMER_END("cc_start_transport_stream_op", 0);
889 return;
890 }
891 if (call != NULL) {
892 gpr_mu_unlock(&calld->mu);
893 grpc_subchannel_call_process_op(exec_ctx, call, op);
894 GPR_TIMER_END("cc_start_transport_stream_op", 0);
895 return;
896 }
897 /* if this is a cancellation, then we can raise our cancelled flag */
898 if (op->cancel_error != GRPC_ERROR_NONE) {
899 if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
900 (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
901 goto retry;
902 } else {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700903 // Stash a copy of cancel_error in our call data, so that we can use
904 // it for subsequent operations. This ensures that if the call is
905 // cancelled before any ops are passed down (e.g., if the deadline
906 // is in the past when the call starts), we can return the right
907 // error to the caller when the first op does get passed down.
908 calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700909 switch (calld->creation_phase) {
910 case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
911 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
912 break;
913 case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
Mark D. Rothd4c0f552016-09-01 09:25:32 -0700914 pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel,
Mark D. Roth72f6da82016-09-02 13:42:38 -0700915 NULL, GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700916 break;
917 }
918 gpr_mu_unlock(&calld->mu);
Mark D. Roth72f6da82016-09-02 13:42:38 -0700919 grpc_transport_stream_op_finish_with_failure(
920 exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700921 GPR_TIMER_END("cc_start_transport_stream_op", 0);
922 return;
923 }
924 }
925 /* if we don't have a subchannel, try to get one */
926 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
927 calld->connected_subchannel == NULL &&
928 op->send_initial_metadata != NULL) {
929 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
Yuchen Zeng19656b12016-09-01 18:00:45 -0700930 grpc_closure_init(&calld->next_step, subchannel_ready, elem);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700931 GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
Yuchen Zeng144ce652016-09-01 18:19:34 -0700932 /* If a subchannel is not available immediately, the polling entity from
933 call_data should be provided to channel_data's interested_parties, so
934 that IO of the lb_policy and resolver could be done under it. */
Mark D. Rothd4c0f552016-09-01 09:25:32 -0700935 if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata,
Mark D. Rothe40dd292016-10-05 14:58:37 -0700936 op->send_initial_metadata_flags,
937 &calld->connected_subchannel, &calld->next_step,
938 GRPC_ERROR_NONE)) {
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700939 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
940 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
Yuchen Zeng19656b12016-09-01 18:00:45 -0700941 } else {
Yuchen Zeng19656b12016-09-01 18:00:45 -0700942 grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
943 chand->interested_parties);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700944 }
945 }
946 /* if we've got a subchannel, then let's ask it to create a call */
947 if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
948 calld->connected_subchannel != NULL) {
949 grpc_subchannel_call *subchannel_call = NULL;
950 grpc_error *error = grpc_connected_subchannel_create_call(
Mark D. Rothaa850a72016-09-26 13:38:02 -0700951 exec_ctx, calld->connected_subchannel, calld->pollent, calld->path,
Mark D. Roth3d883412016-11-07 13:42:54 -0800952 calld->call_start_time, calld->deadline, &subchannel_call);
Mark D. Roth2a5959f2016-09-01 08:20:27 -0700953 if (error != GRPC_ERROR_NONE) {
954 subchannel_call = CANCELLED_CALL;
955 fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
956 grpc_transport_stream_op_finish_with_failure(exec_ctx, op, error);
957 }
958 gpr_atm_rel_store(&calld->subchannel_call,
959 (gpr_atm)(uintptr_t)subchannel_call);
960 retry_waiting_locked(exec_ctx, calld);
961 goto retry;
962 }
963 /* nothing to be done but wait */
964 add_waiting_locked(calld, op);
965 gpr_mu_unlock(&calld->mu);
966 GPR_TIMER_END("cc_start_transport_stream_op", 0);
967}
968
Mark D. Rothe40dd292016-10-05 14:58:37 -0700969// Gets data from the service config. Invoked when the resolver returns
970// its initial result.
971static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
972 grpc_error *error) {
973 grpc_call_element *elem = arg;
974 channel_data *chand = elem->channel_data;
975 call_data *calld = elem->call_data;
976 // If this is an error, there's no point in looking at the service config.
Mark D. Roth196387a2016-10-12 14:53:36 -0700977 if (error == GRPC_ERROR_NONE) {
978 // Get the method config table from channel data.
979 gpr_mu_lock(&chand->mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700980 grpc_mdstr_hash_table *method_params_table = NULL;
981 if (chand->method_params_table != NULL) {
982 method_params_table =
983 grpc_mdstr_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -0700984 }
Mark D. Roth196387a2016-10-12 14:53:36 -0700985 gpr_mu_unlock(&chand->mu);
986 // If the method config table was present, use it.
Mark D. Roth9d480942016-10-19 14:18:05 -0700987 if (method_params_table != NULL) {
988 const method_parameters *method_params =
989 grpc_method_config_table_get(method_params_table, calld->path);
990 if (method_params != NULL) {
991 const bool have_method_timeout =
992 gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
993 if (have_method_timeout ||
994 method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -0700995 gpr_mu_lock(&calld->mu);
Mark D. Roth9d480942016-10-19 14:18:05 -0700996 if (have_method_timeout) {
997 const gpr_timespec per_method_deadline =
998 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Roth196387a2016-10-12 14:53:36 -0700999 if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1000 calld->deadline = per_method_deadline;
1001 // Reset deadline timer.
1002 grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
1003 }
1004 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001005 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Roth196387a2016-10-12 14:53:36 -07001006 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -07001007 method_params->wait_for_ready;
Mark D. Roth196387a2016-10-12 14:53:36 -07001008 }
1009 gpr_mu_unlock(&calld->mu);
1010 }
1011 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001012 grpc_mdstr_hash_table_unref(method_params_table);
Mark D. Roth196387a2016-10-12 14:53:36 -07001013 }
Mark D. Rothe40dd292016-10-05 14:58:37 -07001014 }
Mark D. Roth31292f22016-10-12 13:14:07 -07001015 GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001016}
1017
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001018/* Constructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001019static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1020 grpc_call_element *elem,
1021 grpc_call_element_args *args) {
Mark D. Rothaa850a72016-09-26 13:38:02 -07001022 channel_data *chand = elem->channel_data;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001023 call_data *calld = elem->call_data;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001024 // Initialize data members.
1025 grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
Mark D. Rothaa850a72016-09-26 13:38:02 -07001026 calld->path = GRPC_MDSTR_REF(args->path);
Mark D. Rothff08f332016-10-14 13:01:01 -07001027 calld->call_start_time = args->start_time;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001028 calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1029 calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001030 calld->cancel_error = GRPC_ERROR_NONE;
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001031 gpr_atm_rel_store(&calld->subchannel_call, 0);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001032 gpr_mu_init(&calld->mu);
1033 calld->connected_subchannel = NULL;
1034 calld->waiting_ops = NULL;
1035 calld->waiting_ops_count = 0;
1036 calld->waiting_ops_capacity = 0;
1037 calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1038 calld->owning_call = args->call_stack;
1039 calld->pollent = NULL;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001040 // If the resolver has already returned results, then we can access
1041 // the service config parameters immediately. Otherwise, we need to
1042 // defer that work until the resolver returns an initial result.
1043 // TODO(roth): This code is almost but not quite identical to the code
1044 // in read_service_config() above. It would be nice to find a way to
1045 // combine them, to avoid having to maintain it twice.
1046 gpr_mu_lock(&chand->mu);
1047 if (chand->lb_policy != NULL) {
1048 // We already have a resolver result, so check for service config.
Mark D. Roth9d480942016-10-19 14:18:05 -07001049 if (chand->method_params_table != NULL) {
1050 grpc_mdstr_hash_table *method_params_table =
1051 grpc_mdstr_hash_table_ref(chand->method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -07001052 gpr_mu_unlock(&chand->mu);
Mark D. Roth9d480942016-10-19 14:18:05 -07001053 method_parameters *method_params =
1054 grpc_method_config_table_get(method_params_table, args->path);
1055 if (method_params != NULL) {
1056 if (gpr_time_cmp(method_params->timeout,
1057 gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001058 gpr_timespec per_method_deadline =
Mark D. Roth9d480942016-10-19 14:18:05 -07001059 gpr_time_add(calld->call_start_time, method_params->timeout);
Mark D. Rothe40dd292016-10-05 14:58:37 -07001060 calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
1061 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001062 if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
Mark D. Rothe40dd292016-10-05 14:58:37 -07001063 calld->wait_for_ready_from_service_config =
Mark D. Roth9d480942016-10-19 14:18:05 -07001064 method_params->wait_for_ready;
Mark D. Rothe40dd292016-10-05 14:58:37 -07001065 }
1066 }
Mark D. Roth9d480942016-10-19 14:18:05 -07001067 grpc_mdstr_hash_table_unref(method_params_table);
Mark D. Rothe40dd292016-10-05 14:58:37 -07001068 } else {
1069 gpr_mu_unlock(&chand->mu);
1070 }
1071 } else {
1072 // We don't yet have a resolver result, so register a callback to
1073 // get the service config data once the resolver returns.
Mark D. Roth31292f22016-10-12 13:14:07 -07001074 // Take a reference to the call stack to be owned by the callback.
1075 GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
Mark D. Rothe40dd292016-10-05 14:58:37 -07001076 grpc_closure_init(&calld->read_service_config, read_service_config, elem);
1077 grpc_closure_list_append(&chand->waiting_for_config_closures,
1078 &calld->read_service_config, GRPC_ERROR_NONE);
1079 gpr_mu_unlock(&chand->mu);
1080 }
1081 // Start the deadline timer with the current deadline value. If we
1082 // do not yet have service config data, then the timer may be reset
1083 // later.
1084 grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
Mark D. Roth0badbe82016-06-23 10:15:12 -07001085 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001086}
1087
1088/* Destructor for call_data */
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001089static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1090 grpc_call_element *elem,
1091 const grpc_call_final_info *final_info,
1092 void *and_free_memory) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001093 call_data *calld = elem->call_data;
Mark D. Rothf28763c2016-09-14 15:18:40 -07001094 grpc_deadline_state_destroy(exec_ctx, elem);
Mark D. Rothaa850a72016-09-26 13:38:02 -07001095 GRPC_MDSTR_UNREF(calld->path);
Mark D. Rothf28763c2016-09-14 15:18:40 -07001096 GRPC_ERROR_UNREF(calld->cancel_error);
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001097 grpc_subchannel_call *call = GET_CALL(calld);
1098 if (call != NULL && call != CANCELLED_CALL) {
1099 GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1100 }
1101 GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
1102 gpr_mu_destroy(&calld->mu);
1103 GPR_ASSERT(calld->waiting_ops_count == 0);
Craig Tiller693d3942016-10-27 16:51:25 -07001104 if (calld->connected_subchannel != NULL) {
1105 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1106 "picked");
1107 }
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001108 gpr_free(calld->waiting_ops);
Craig Tiller2c8063c2016-03-22 22:12:15 -07001109 gpr_free(and_free_memory);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001110}
1111
David Garcia Quintasf72eb972016-05-03 18:28:09 -07001112static void cc_set_pollset_or_pollset_set(grpc_exec_ctx *exec_ctx,
1113 grpc_call_element *elem,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001114 grpc_polling_entity *pollent) {
Craig Tiller577c9b22015-11-02 14:11:15 -08001115 call_data *calld = elem->call_data;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -07001116 calld->pollent = pollent;
Craig Tiller577c9b22015-11-02 14:11:15 -08001117}
1118
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001119/*************************************************************************
1120 * EXPORTED SYMBOLS
1121 */
1122
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001123const grpc_channel_filter grpc_client_channel_filter = {
Craig Tillerf40df232016-03-25 13:38:14 -07001124 cc_start_transport_stream_op,
1125 cc_start_transport_op,
1126 sizeof(call_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001127 cc_init_call_elem,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07001128 cc_set_pollset_or_pollset_set,
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001129 cc_destroy_call_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001130 sizeof(channel_data),
Mark D. Roth2a5959f2016-09-01 08:20:27 -07001131 cc_init_channel_elem,
1132 cc_destroy_channel_elem,
Craig Tillerf40df232016-03-25 13:38:14 -07001133 cc_get_peer,
Mark D. Rothb2d24882016-10-27 15:44:07 -07001134 cc_get_channel_info,
Craig Tillerf40df232016-03-25 13:38:14 -07001135 "client-channel",
Craig Tiller87d5b192015-04-16 14:37:57 -07001136};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001137
Mark D. Roth60534972016-09-20 08:37:12 -07001138void grpc_client_channel_finish_initialization(
Mark D. Roth0e48a9a2016-09-08 14:14:39 -07001139 grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
1140 grpc_resolver *resolver,
1141 grpc_client_channel_factory *client_channel_factory) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001142 /* post construction initialization: set the transport setup pointer */
Mark D. Roth7f7d1652016-09-20 10:46:15 -07001143 GPR_ASSERT(client_channel_factory != NULL);
Craig Tillera82950e2015-09-22 12:33:20 -07001144 grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001145 channel_data *chand = elem->channel_data;
Mark D. Rothff4df062016-08-22 15:02:49 -07001146 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -07001147 GPR_ASSERT(!chand->resolver);
Craig Tillerf5f17122015-06-25 08:47:26 -07001148 chand->resolver = resolver;
Craig Tillera82950e2015-09-22 12:33:20 -07001149 GRPC_RESOLVER_REF(resolver, "channel");
1150 if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
1151 chand->exit_idle_when_lb_policy_arrives) {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001152 chand->started_resolving = true;
Craig Tiller906e3bc2015-11-24 07:31:31 -08001153 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth046cf762016-09-26 11:13:51 -07001154 grpc_resolver_next(exec_ctx, resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -07001155 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -07001156 }
Mark D. Roth0e48a9a2016-09-08 14:14:39 -07001157 chand->client_channel_factory = client_channel_factory;
1158 grpc_client_channel_factory_ref(client_channel_factory);
Mark D. Rothff4df062016-08-22 15:02:49 -07001159 gpr_mu_unlock(&chand->mu);
Craig Tiller190d3602015-02-18 09:23:38 -08001160}
Craig Tiller48cb07c2015-07-15 16:16:15 -07001161
Craig Tillera82950e2015-09-22 12:33:20 -07001162grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1163 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001164 channel_data *chand = elem->channel_data;
1165 grpc_connectivity_state out;
Mark D. Rothff4df062016-08-22 15:02:49 -07001166 gpr_mu_lock(&chand->mu);
Craig Tiller804ff712016-05-05 16:25:40 -07001167 out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -07001168 if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
1169 if (chand->lb_policy != NULL) {
1170 grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
1171 } else {
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001172 chand->exit_idle_when_lb_policy_arrives = true;
Craig Tillera82950e2015-09-22 12:33:20 -07001173 if (!chand->started_resolving && chand->resolver != NULL) {
Craig Tiller906e3bc2015-11-24 07:31:31 -08001174 GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
Mark D. Roth4c0fe492016-08-31 13:51:55 -07001175 chand->started_resolving = true;
Mark D. Roth046cf762016-09-26 11:13:51 -07001176 grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
Mark D. Rothff4df062016-08-22 15:02:49 -07001177 &chand->on_resolver_result_changed);
Craig Tillera82950e2015-09-22 12:33:20 -07001178 }
Craig Tiller48cb07c2015-07-15 16:16:15 -07001179 }
Craig Tillera82950e2015-09-22 12:33:20 -07001180 }
Mark D. Rothff4df062016-08-22 15:02:49 -07001181 gpr_mu_unlock(&chand->mu);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001182 return out;
1183}
1184
Craig Tiller86c99582015-11-25 15:22:26 -08001185typedef struct {
1186 channel_data *chand;
1187 grpc_pollset *pollset;
1188 grpc_closure *on_complete;
1189 grpc_closure my_closure;
1190} external_connectivity_watcher;
1191
Craig Tiller1d881fb2015-12-01 07:39:04 -08001192static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -07001193 grpc_error *error) {
Craig Tiller86c99582015-11-25 15:22:26 -08001194 external_connectivity_watcher *w = arg;
1195 grpc_closure *follow_up = w->on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001196 grpc_pollset_set_del_pollset(exec_ctx, w->chand->interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -08001197 w->pollset);
1198 GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1199 "external_connectivity_watcher");
Craig Tiller86c99582015-11-25 15:22:26 -08001200 gpr_free(w);
Craig Tiller804ff712016-05-05 16:25:40 -07001201 follow_up->cb(exec_ctx, follow_up->cb_arg, error);
Craig Tiller86c99582015-11-25 15:22:26 -08001202}
1203
Craig Tillera82950e2015-09-22 12:33:20 -07001204void grpc_client_channel_watch_connectivity_state(
Craig Tiller906e3bc2015-11-24 07:31:31 -08001205 grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
Craig Tillera82950e2015-09-22 12:33:20 -07001206 grpc_connectivity_state *state, grpc_closure *on_complete) {
Craig Tiller48cb07c2015-07-15 16:16:15 -07001207 channel_data *chand = elem->channel_data;
Craig Tiller86c99582015-11-25 15:22:26 -08001208 external_connectivity_watcher *w = gpr_malloc(sizeof(*w));
1209 w->chand = chand;
1210 w->pollset = pollset;
1211 w->on_complete = on_complete;
Craig Tiller69b093b2016-02-25 19:04:07 -08001212 grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
Craig Tiller86c99582015-11-25 15:22:26 -08001213 grpc_closure_init(&w->my_closure, on_external_watch_complete, w);
Craig Tiller1d881fb2015-12-01 07:39:04 -08001214 GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1215 "external_connectivity_watcher");
Mark D. Rothff4df062016-08-22 15:02:49 -07001216 gpr_mu_lock(&chand->mu);
Craig Tillera82950e2015-09-22 12:33:20 -07001217 grpc_connectivity_state_notify_on_state_change(
Craig Tiller86c99582015-11-25 15:22:26 -08001218 exec_ctx, &chand->state_tracker, state, &w->my_closure);
Mark D. Rothff4df062016-08-22 15:02:49 -07001219 gpr_mu_unlock(&chand->mu);
Craig Tiller48cb07c2015-07-15 16:16:15 -07001220}