blob: 9e83de28e5cdaaf2acc5d2cd6b44d77ed55a66ba [file] [log] [blame]
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
Craig Tillereb3b12e2015-06-26 14:42:49 -070034#include <string.h>
35
36#include <grpc/support/alloc.h>
Craig Tillerd4c98332016-03-31 13:45:47 -070037#include "src/core/ext/client_config/lb_policy_registry.h"
Craig Tiller9533d042016-03-25 17:11:06 -070038#include "src/core/lib/transport/connectivity_state.h"
Craig Tillereb3b12e2015-06-26 14:42:49 -070039
Craig Tillera82950e2015-09-22 12:33:20 -070040typedef struct pending_pick {
Craig Tillereb3b12e2015-06-26 14:42:49 -070041 struct pending_pick *next;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -070042 grpc_polling_entity *pollent;
Craig Tiller8c0d96f2016-03-11 14:27:52 -080043 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -080044 grpc_connected_subchannel **target;
Craig Tiller33825112015-09-18 07:44:19 -070045 grpc_closure *on_complete;
Craig Tillereb3b12e2015-06-26 14:42:49 -070046} pending_pick;
47
Craig Tillera82950e2015-09-22 12:33:20 -070048typedef struct {
Craig Tillereb3b12e2015-06-26 14:42:49 -070049 /** base policy: must be first */
50 grpc_lb_policy base;
Craig Tillereb3b12e2015-06-26 14:42:49 -070051 /** all our subchannels */
52 grpc_subchannel **subchannels;
53 size_t num_subchannels;
54
Craig Tiller33825112015-09-18 07:44:19 -070055 grpc_closure connectivity_changed;
Craig Tillereb3b12e2015-06-26 14:42:49 -070056
Craig Tiller86c0f8a2015-12-01 20:05:40 -080057 /** the selected channel (a grpc_connected_subchannel) */
58 gpr_atm selected;
Craig Tiller320bee02016-01-06 17:33:45 -080059
60 /** mutex protecting remaining members */
61 gpr_mu mu;
Craig Tillereb3b12e2015-06-26 14:42:49 -070062 /** have we started picking? */
63 int started_picking;
Craig Tillera14215a2015-07-17 17:21:08 -070064 /** are we shut down? */
65 int shutdown;
Craig Tillereb3b12e2015-06-26 14:42:49 -070066 /** which subchannel are we watching? */
67 size_t checking_subchannel;
68 /** what is the connectivity of that channel? */
69 grpc_connectivity_state checking_connectivity;
70 /** list of picks that are waiting on connectivity */
71 pending_pick *pending_picks;
Craig Tillerc7b5f762015-06-27 11:48:42 -070072
73 /** our connectivity state tracker */
74 grpc_connectivity_state_tracker state_tracker;
Craig Tillereb3b12e2015-06-26 14:42:49 -070075} pick_first_lb_policy;
76
Craig Tiller81afdda2016-01-11 17:09:18 -080077#define GET_SELECTED(p) \
Craig Tillerd9d474a2016-01-26 06:50:51 -080078 ((grpc_connected_subchannel *)gpr_atm_acq_load(&(p)->selected))
Craig Tiller86c0f8a2015-12-01 20:05:40 -080079
Craig Tillerfb433852016-03-29 08:51:07 -070080static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -070081 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller86c0f8a2015-12-01 20:05:40 -080082 grpc_connected_subchannel *selected = GET_SELECTED(p);
Craig Tillerd7b68e72015-06-28 11:41:09 -070083 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -070084 GPR_ASSERT(p->pending_picks == NULL);
85 for (i = 0; i < p->num_subchannels; i++) {
86 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
87 }
Craig Tiller86c0f8a2015-12-01 20:05:40 -080088 if (selected != NULL) {
89 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, selected, "picked_first");
Craig Tiller89a768e2015-10-06 09:55:59 -070090 }
Craig Tillera82950e2015-09-22 12:33:20 -070091 grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
92 gpr_free(p->subchannels);
93 gpr_mu_destroy(&p->mu);
94 gpr_free(p);
Craig Tillereb3b12e2015-06-26 14:42:49 -070095}
96
Craig Tillerfb433852016-03-29 08:51:07 -070097static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -070098 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerd2cc4592015-07-01 07:50:47 -070099 pending_pick *pp;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800100 grpc_connected_subchannel *selected;
Craig Tillera82950e2015-09-22 12:33:20 -0700101 gpr_mu_lock(&p->mu);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800102 selected = GET_SELECTED(p);
Craig Tillera14215a2015-07-17 17:21:08 -0700103 p->shutdown = 1;
Craig Tiller5795da72015-09-17 15:27:13 -0700104 pp = p->pending_picks;
105 p->pending_picks = NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700106 grpc_connectivity_state_set(
Craig Tillerd925c932016-06-06 08:38:50 -0700107 exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700108 GRPC_ERROR_CREATE("Channel shutdown"), "shutdown");
Craig Tillerf036a642015-12-01 17:00:40 -0800109 /* cancel subscription */
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800110 if (selected != NULL) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800111 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800112 exec_ctx, selected, NULL, NULL, &p->connectivity_changed);
Craig Tillere2b86c72016-04-14 17:34:01 -0700113 } else if (p->num_subchannels > 0) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800114 grpc_subchannel_notify_on_state_change(
115 exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
116 &p->connectivity_changed);
Craig Tiller48613042015-11-29 14:45:11 -0800117 }
Craig Tillera82950e2015-09-22 12:33:20 -0700118 gpr_mu_unlock(&p->mu);
119 while (pp != NULL) {
120 pending_pick *next = pp->next;
121 *pp->target = NULL;
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700122 grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
David Garcia Quintas69ff63d2016-06-06 16:39:47 -0700123 p->base.interested_parties);
Craig Tiller332f1b32016-05-24 13:21:21 -0700124 grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700125 gpr_free(pp);
126 pp = next;
127 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700128}
129
Craig Tiller577c9b22015-11-02 14:11:15 -0800130static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
Mark D. Roth5f844002016-09-08 08:20:53 -0700131 grpc_connected_subchannel **target,
132 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800133 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
134 pending_pick *pp;
135 gpr_mu_lock(&p->mu);
136 pp = p->pending_picks;
137 p->pending_picks = NULL;
138 while (pp != NULL) {
139 pending_pick *next = pp->next;
140 if (pp->target == target) {
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700141 grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
David Garcia Quintas69ff63d2016-06-06 16:39:47 -0700142 p->base.interested_parties);
Craig Tiller577c9b22015-11-02 14:11:15 -0800143 *target = NULL;
Mark D. Roth932b10c2016-09-09 08:44:30 -0700144 grpc_exec_ctx_sched(
145 exec_ctx, pp->on_complete,
146 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1), NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800147 gpr_free(pp);
148 } else {
149 pp->next = p->pending_picks;
150 p->pending_picks = pp;
151 }
152 pp = next;
153 }
154 gpr_mu_unlock(&p->mu);
Mark D. Roth5f844002016-09-08 08:20:53 -0700155 GRPC_ERROR_UNREF(error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800156}
157
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800158static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
159 uint32_t initial_metadata_flags_mask,
Mark D. Rothe65ff112016-09-09 13:48:38 -0700160 uint32_t initial_metadata_flags_eq,
161 grpc_error *error) {
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800162 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
163 pending_pick *pp;
164 gpr_mu_lock(&p->mu);
165 pp = p->pending_picks;
166 p->pending_picks = NULL;
167 while (pp != NULL) {
168 pending_pick *next = pp->next;
169 if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
170 initial_metadata_flags_eq) {
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700171 grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
David Garcia Quintas69ff63d2016-06-06 16:39:47 -0700172 p->base.interested_parties);
Craig Tiller332f1b32016-05-24 13:21:21 -0700173 grpc_exec_ctx_sched(exec_ctx, pp->on_complete,
Mark D. Rothe65ff112016-09-09 13:48:38 -0700174 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled",
175 &error, 1), NULL);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800176 gpr_free(pp);
177 } else {
178 pp->next = p->pending_picks;
179 p->pending_picks = pp;
180 }
181 pp = next;
182 }
183 gpr_mu_unlock(&p->mu);
Mark D. Rothe65ff112016-09-09 13:48:38 -0700184 GRPC_ERROR_UNREF(error);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800185}
186
Craig Tillera82950e2015-09-22 12:33:20 -0700187static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700188 p->started_picking = 1;
189 p->checking_subchannel = 0;
190 p->checking_connectivity = GRPC_CHANNEL_IDLE;
Craig Tiller48613042015-11-29 14:45:11 -0800191 GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700192 grpc_subchannel_notify_on_state_change(
193 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800194 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800195 &p->connectivity_changed);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700196}
197
Craig Tillerfb433852016-03-29 08:51:07 -0700198static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -0700199 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
200 gpr_mu_lock(&p->mu);
201 if (!p->started_picking) {
202 start_picking(exec_ctx, p);
203 }
204 gpr_mu_unlock(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700205}
206
Craig Tillerfb433852016-03-29 08:51:07 -0700207static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700208 grpc_polling_entity *pollent,
209 grpc_metadata_batch *initial_metadata,
Craig Tiller41dac842016-03-31 14:01:53 -0700210 uint32_t initial_metadata_flags,
Craig Tillerfb433852016-03-29 08:51:07 -0700211 grpc_connected_subchannel **target,
212 grpc_closure *on_complete) {
Craig Tillera82950e2015-09-22 12:33:20 -0700213 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller45724b32015-09-22 10:42:19 -0700214 pending_pick *pp;
Craig Tiller320bee02016-01-06 17:33:45 -0800215
216 /* Check atomically for a selected channel */
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800217 grpc_connected_subchannel *selected = GET_SELECTED(p);
218 if (selected != NULL) {
219 *target = selected;
220 return 1;
221 }
Craig Tiller320bee02016-01-06 17:33:45 -0800222
223 /* No subchannel selected yet, so acquire lock and then attempt again */
Craig Tillera82950e2015-09-22 12:33:20 -0700224 gpr_mu_lock(&p->mu);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800225 selected = GET_SELECTED(p);
226 if (selected) {
Craig Tillera82950e2015-09-22 12:33:20 -0700227 gpr_mu_unlock(&p->mu);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800228 *target = selected;
Craig Tiller577c9b22015-11-02 14:11:15 -0800229 return 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700230 } else {
231 if (!p->started_picking) {
232 start_picking(exec_ctx, p);
Craig Tiller45724b32015-09-22 10:42:19 -0700233 }
David Garcia Quintas69ff63d2016-06-06 16:39:47 -0700234 grpc_polling_entity_add_to_pollset_set(exec_ctx, pollent,
235 p->base.interested_parties);
Craig Tillera82950e2015-09-22 12:33:20 -0700236 pp = gpr_malloc(sizeof(*pp));
237 pp->next = p->pending_picks;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700238 pp->pollent = pollent;
Craig Tillera82950e2015-09-22 12:33:20 -0700239 pp->target = target;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800240 pp->initial_metadata_flags = initial_metadata_flags;
Craig Tillera82950e2015-09-22 12:33:20 -0700241 pp->on_complete = on_complete;
242 p->pending_picks = pp;
243 gpr_mu_unlock(&p->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800244 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700245 }
Craig Tiller45724b32015-09-22 10:42:19 -0700246}
247
Craig Tiller1f41b6b2015-10-09 15:07:02 -0700248static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700249 grpc_error *error) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700250 pick_first_lb_policy *p = arg;
251 size_t i;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700252 size_t num_subchannels = p->num_subchannels;
253 grpc_subchannel **subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700254
255 gpr_mu_lock(&p->mu);
256 subchannels = p->subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700257 p->num_subchannels = 0;
258 p->subchannels = NULL;
259 gpr_mu_unlock(&p->mu);
Craig Tiller48613042015-11-29 14:45:11 -0800260 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700261
262 for (i = 0; i < num_subchannels; i++) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700263 GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
264 }
265
266 gpr_free(subchannels);
267}
268
Craig Tillera82950e2015-09-22 12:33:20 -0700269static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller804ff712016-05-05 16:25:40 -0700270 grpc_error *error) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700271 pick_first_lb_policy *p = arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800272 grpc_subchannel *selected_subchannel;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700273 pending_pick *pp;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800274 grpc_connected_subchannel *selected;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700275
Craig Tillerf707d622016-05-06 14:26:12 -0700276 GRPC_ERROR_REF(error);
Craig Tiller804ff712016-05-05 16:25:40 -0700277
Craig Tillera82950e2015-09-22 12:33:20 -0700278 gpr_mu_lock(&p->mu);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700279
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800280 selected = GET_SELECTED(p);
281
Craig Tillera82950e2015-09-22 12:33:20 -0700282 if (p->shutdown) {
283 gpr_mu_unlock(&p->mu);
Craig Tiller48613042015-11-29 14:45:11 -0800284 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tillerae125932016-05-13 16:34:29 -0700285 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700286 return;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800287 } else if (selected != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800288 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
289 /* if the selected channel goes bad, we're done */
Craig Tiller48ed92e2016-06-02 11:07:12 -0700290 p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
Craig Tillercb2609f2015-11-24 17:19:19 -0800291 }
Craig Tillera82950e2015-09-22 12:33:20 -0700292 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
Craig Tillerf707d622016-05-06 14:26:12 -0700293 p->checking_connectivity, GRPC_ERROR_REF(error),
Craig Tiller804ff712016-05-05 16:25:40 -0700294 "selected_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700295 if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillerab33b482015-11-21 08:11:04 -0800296 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800297 exec_ctx, selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800298 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700299 } else {
Craig Tiller48613042015-11-29 14:45:11 -0800300 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700301 }
Craig Tillera82950e2015-09-22 12:33:20 -0700302 } else {
303 loop:
304 switch (p->checking_connectivity) {
305 case GRPC_CHANNEL_READY:
306 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
Craig Tiller804ff712016-05-05 16:25:40 -0700307 GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
308 "connecting_ready");
Craig Tillerb5585d42015-11-17 07:18:31 -0800309 selected_subchannel = p->subchannels[p->checking_subchannel];
Craig Tiller81afdda2016-01-11 17:09:18 -0800310 selected =
311 grpc_subchannel_get_connected_subchannel(selected_subchannel);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800312 GPR_ASSERT(selected != NULL);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800313 GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked_first");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700314 /* drop the pick list: we are connected now */
Craig Tiller48613042015-11-29 14:45:11 -0800315 GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
Craig Tillerd9d474a2016-01-26 06:50:51 -0800316 gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
Craig Tiller332f1b32016-05-24 13:21:21 -0700317 grpc_exec_ctx_sched(exec_ctx,
318 grpc_closure_create(destroy_subchannels, p),
319 GRPC_ERROR_NONE, NULL);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700320 /* update any calls that were waiting for a pick */
Craig Tillera82950e2015-09-22 12:33:20 -0700321 while ((pp = p->pending_picks)) {
322 p->pending_picks = pp->next;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800323 *pp->target = selected;
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700324 grpc_polling_entity_del_from_pollset_set(exec_ctx, pp->pollent,
David Garcia Quintas69ff63d2016-06-06 16:39:47 -0700325 p->base.interested_parties);
Craig Tiller332f1b32016-05-24 13:21:21 -0700326 grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700327 gpr_free(pp);
328 }
Craig Tillerab33b482015-11-21 08:11:04 -0800329 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800330 exec_ctx, selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800331 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700332 break;
333 case GRPC_CHANNEL_TRANSIENT_FAILURE:
Craig Tillera82950e2015-09-22 12:33:20 -0700334 p->checking_subchannel =
335 (p->checking_subchannel + 1) % p->num_subchannels;
Craig Tiller131b6de2016-03-31 17:05:28 -0700336 if (p->checking_subchannel == 0) {
337 /* only trigger transient failure when we've tried all alternatives */
Craig Tiller804ff712016-05-05 16:25:40 -0700338 grpc_connectivity_state_set(
339 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tillerf707d622016-05-06 14:26:12 -0700340 GRPC_ERROR_REF(error), "connecting_transient_failure");
Craig Tiller131b6de2016-03-31 17:05:28 -0700341 }
Craig Tillerf707d622016-05-06 14:26:12 -0700342 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700343 p->checking_connectivity = grpc_subchannel_check_connectivity(
Craig Tiller804ff712016-05-05 16:25:40 -0700344 p->subchannels[p->checking_subchannel], &error);
Craig Tillera82950e2015-09-22 12:33:20 -0700345 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
346 grpc_subchannel_notify_on_state_change(
347 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800348 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800349 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700350 } else {
351 goto loop;
352 }
353 break;
354 case GRPC_CHANNEL_CONNECTING:
355 case GRPC_CHANNEL_IDLE:
Craig Tiller804ff712016-05-05 16:25:40 -0700356 grpc_connectivity_state_set(
357 exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING,
Craig Tillerf707d622016-05-06 14:26:12 -0700358 GRPC_ERROR_REF(error), "connecting_changed");
Craig Tillera82950e2015-09-22 12:33:20 -0700359 grpc_subchannel_notify_on_state_change(
360 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800361 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800362 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700363 break;
Craig Tiller48ed92e2016-06-02 11:07:12 -0700364 case GRPC_CHANNEL_SHUTDOWN:
Craig Tillera82950e2015-09-22 12:33:20 -0700365 p->num_subchannels--;
Craig Tiller86c99582015-11-25 15:22:26 -0800366 GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
367 p->subchannels[p->num_subchannels]);
Craig Tillera82950e2015-09-22 12:33:20 -0700368 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
369 "pick_first");
370 if (p->num_subchannels == 0) {
Craig Tiller804ff712016-05-05 16:25:40 -0700371 grpc_connectivity_state_set(
Craig Tillerd925c932016-06-06 08:38:50 -0700372 exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700373 GRPC_ERROR_CREATE_REFERENCING("Pick first exhausted channels",
374 &error, 1),
375 "no_more_channels");
Craig Tillera82950e2015-09-22 12:33:20 -0700376 while ((pp = p->pending_picks)) {
377 p->pending_picks = pp->next;
378 *pp->target = NULL;
Craig Tiller332f1b32016-05-24 13:21:21 -0700379 grpc_exec_ctx_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE,
380 NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700381 gpr_free(pp);
382 }
Craig Tiller1d881fb2015-12-01 07:39:04 -0800383 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
384 "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700385 } else {
Craig Tiller804ff712016-05-05 16:25:40 -0700386 grpc_connectivity_state_set(
387 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tillerf707d622016-05-06 14:26:12 -0700388 GRPC_ERROR_REF(error), "subchannel_failed");
Craig Tillera82950e2015-09-22 12:33:20 -0700389 p->checking_subchannel %= p->num_subchannels;
Craig Tillerf707d622016-05-06 14:26:12 -0700390 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700391 p->checking_connectivity = grpc_subchannel_check_connectivity(
Craig Tiller804ff712016-05-05 16:25:40 -0700392 p->subchannels[p->checking_subchannel], &error);
Craig Tillera82950e2015-09-22 12:33:20 -0700393 goto loop;
394 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700395 }
Craig Tillera82950e2015-09-22 12:33:20 -0700396 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700397
Craig Tillera82950e2015-09-22 12:33:20 -0700398 gpr_mu_unlock(&p->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700399
Craig Tillerf707d622016-05-06 14:26:12 -0700400 GRPC_ERROR_UNREF(error);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700401}
402
Craig Tillera82950e2015-09-22 12:33:20 -0700403static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
Craig Tiller804ff712016-05-05 16:25:40 -0700404 grpc_lb_policy *pol,
405 grpc_error **error) {
Craig Tillera82950e2015-09-22 12:33:20 -0700406 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerc7b5f762015-06-27 11:48:42 -0700407 grpc_connectivity_state st;
Craig Tillera82950e2015-09-22 12:33:20 -0700408 gpr_mu_lock(&p->mu);
Craig Tiller804ff712016-05-05 16:25:40 -0700409 st = grpc_connectivity_state_check(&p->state_tracker, error);
Craig Tillera82950e2015-09-22 12:33:20 -0700410 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700411 return st;
412}
413
Craig Tillerfb433852016-03-29 08:51:07 -0700414static void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx,
415 grpc_lb_policy *pol,
416 grpc_connectivity_state *current,
417 grpc_closure *notify) {
Craig Tillera82950e2015-09-22 12:33:20 -0700418 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
419 gpr_mu_lock(&p->mu);
420 grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
421 current, notify);
422 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700423}
424
Craig Tillerfb433852016-03-29 08:51:07 -0700425static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
426 grpc_closure *closure) {
Craig Tiller28bf8912015-12-07 16:07:04 -0800427 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller093193e2016-01-07 07:14:44 -0800428 grpc_connected_subchannel *selected = GET_SELECTED(p);
429 if (selected) {
430 grpc_connected_subchannel_ping(exec_ctx, selected, closure);
Craig Tiller28bf8912015-12-07 16:07:04 -0800431 } else {
Craig Tiller332f1b32016-05-24 13:21:21 -0700432 grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CREATE("Not connected"),
433 NULL);
Craig Tiller28bf8912015-12-07 16:07:04 -0800434 }
Craig Tiller28bf8912015-12-07 16:07:04 -0800435}
436
Craig Tillereb3b12e2015-06-26 14:42:49 -0700437static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
Craig Tillerc5ff7812016-03-28 12:45:55 -0700438 pf_destroy, pf_shutdown, pf_pick,
439 pf_cancel_pick, pf_cancel_picks, pf_ping_one,
440 pf_exit_idle, pf_check_connectivity, pf_notify_on_state_change};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700441
Craig Tillera82950e2015-09-22 12:33:20 -0700442static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700443
Craig Tillera82950e2015-09-22 12:33:20 -0700444static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700445
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700446static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
447 grpc_lb_policy_factory *factory,
Craig Tillera82950e2015-09-22 12:33:20 -0700448 grpc_lb_policy_args *args) {
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700449 GPR_ASSERT(args->addresses != NULL);
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700450 GPR_ASSERT(args->client_channel_factory != NULL);
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700451
452 if (args->addresses->naddrs == 0) return NULL;
453
Craig Tillera82950e2015-09-22 12:33:20 -0700454 pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
Craig Tillera82950e2015-09-22 12:33:20 -0700455 memset(p, 0, sizeof(*p));
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700456
Craig Tillera82950e2015-09-22 12:33:20 -0700457 p->subchannels =
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700458 gpr_malloc(sizeof(grpc_subchannel *) * args->addresses->naddrs);
459 memset(p->subchannels, 0, sizeof(*p->subchannels) * args->addresses->naddrs);
460 grpc_subchannel_args sc_args;
461 size_t subchannel_idx = 0;
462 for (size_t i = 0; i < args->addresses->naddrs; i++) {
463 memset(&sc_args, 0, sizeof(grpc_subchannel_args));
464 sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
465 sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
466
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700467 grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
468 exec_ctx, args->client_channel_factory, &sc_args);
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700469
470 if (subchannel != NULL) {
471 p->subchannels[subchannel_idx++] = subchannel;
472 }
473 }
474 if (subchannel_idx == 0) {
475 gpr_free(p->subchannels);
476 gpr_free(p);
477 return NULL;
478 }
479 p->num_subchannels = subchannel_idx;
480
481 grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
Craig Tillera82950e2015-09-22 12:33:20 -0700482 grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
483 gpr_mu_init(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700484 return &p->base;
485}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700486
487static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700488 pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
489 "pick_first"};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700490
491static grpc_lb_policy_factory pick_first_lb_policy_factory = {
Craig Tillera82950e2015-09-22 12:33:20 -0700492 &pick_first_factory_vtable};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700493
Craig Tillerfb433852016-03-29 08:51:07 -0700494static grpc_lb_policy_factory *pick_first_lb_factory_create() {
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700495 return &pick_first_lb_policy_factory;
496}
Craig Tillerfb433852016-03-29 08:51:07 -0700497
498/* Plugin registration */
499
500void grpc_lb_policy_pick_first_init() {
Craig Tiller3113ef42016-03-29 09:03:14 -0700501 grpc_register_lb_policy(pick_first_lb_factory_create());
Craig Tillerfb433852016-03-29 08:51:07 -0700502}
503
504void grpc_lb_policy_pick_first_shutdown() {}