blob: 2833f112f4d17f42eb03ef1f97eead98b3669690 [file] [log] [blame]
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07001/*
2 *
murgatroid993466c4b2016-01-12 10:26:04 -08003 * Copyright 2015-2016, 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
Vijay Paie9ef5362016-02-25 18:10:24 -080034#include "src/core/client_config/lb_policies/pick_first.h"
Craig Tiller69b093b2016-02-25 19:04:07 -080035#include "src/core/client_config/lb_policy_factory.h"
Craig Tillereb3b12e2015-06-26 14:42:49 -070036
37#include <string.h>
38
39#include <grpc/support/alloc.h>
Craig Tiller08a1cf82015-06-29 09:37:52 -070040#include "src/core/transport/connectivity_state.h"
Craig Tillereb3b12e2015-06-26 14:42:49 -070041
Craig Tillera82950e2015-09-22 12:33:20 -070042typedef struct pending_pick {
Craig Tillereb3b12e2015-06-26 14:42:49 -070043 struct pending_pick *next;
44 grpc_pollset *pollset;
Craig Tillerb5585d42015-11-17 07:18:31 -080045 grpc_connected_subchannel **target;
Craig Tiller33825112015-09-18 07:44:19 -070046 grpc_closure *on_complete;
Craig Tillereb3b12e2015-06-26 14:42:49 -070047} pending_pick;
48
Craig Tillera82950e2015-09-22 12:33:20 -070049typedef struct {
Craig Tillereb3b12e2015-06-26 14:42:49 -070050 /** base policy: must be first */
51 grpc_lb_policy base;
Craig Tillereb3b12e2015-06-26 14:42:49 -070052 /** all our subchannels */
53 grpc_subchannel **subchannels;
54 size_t num_subchannels;
55
Craig Tiller33825112015-09-18 07:44:19 -070056 grpc_closure connectivity_changed;
Craig Tillereb3b12e2015-06-26 14:42:49 -070057
Craig Tiller86c0f8a2015-12-01 20:05:40 -080058 /** the selected channel (a grpc_connected_subchannel) */
59 gpr_atm selected;
Craig Tiller320bee02016-01-06 17:33:45 -080060
61 /** mutex protecting remaining members */
62 gpr_mu mu;
Craig Tillereb3b12e2015-06-26 14:42:49 -070063 /** have we started picking? */
64 int started_picking;
Craig Tillera14215a2015-07-17 17:21:08 -070065 /** are we shut down? */
66 int shutdown;
Craig Tillereb3b12e2015-06-26 14:42:49 -070067 /** which subchannel are we watching? */
68 size_t checking_subchannel;
69 /** what is the connectivity of that channel? */
70 grpc_connectivity_state checking_connectivity;
71 /** list of picks that are waiting on connectivity */
72 pending_pick *pending_picks;
Craig Tillerc7b5f762015-06-27 11:48:42 -070073
74 /** our connectivity state tracker */
75 grpc_connectivity_state_tracker state_tracker;
Craig Tillereb3b12e2015-06-26 14:42:49 -070076} pick_first_lb_policy;
77
Craig Tiller81afdda2016-01-11 17:09:18 -080078#define GET_SELECTED(p) \
Craig Tillerd9d474a2016-01-26 06:50:51 -080079 ((grpc_connected_subchannel *)gpr_atm_acq_load(&(p)->selected))
Craig Tiller86c0f8a2015-12-01 20:05:40 -080080
Craig Tillera82950e2015-09-22 12:33:20 -070081void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
82 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller86c0f8a2015-12-01 20:05:40 -080083 grpc_connected_subchannel *selected = GET_SELECTED(p);
Craig Tillerd7b68e72015-06-28 11:41:09 -070084 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -070085 GPR_ASSERT(p->pending_picks == NULL);
86 for (i = 0; i < p->num_subchannels; i++) {
87 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
88 }
Craig Tiller86c0f8a2015-12-01 20:05:40 -080089 if (selected != NULL) {
90 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, selected, "picked_first");
Craig Tiller89a768e2015-10-06 09:55:59 -070091 }
Craig Tillera82950e2015-09-22 12:33:20 -070092 grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
93 gpr_free(p->subchannels);
94 gpr_mu_destroy(&p->mu);
95 gpr_free(p);
Craig Tillereb3b12e2015-06-26 14:42:49 -070096}
97
Craig Tillera82950e2015-09-22 12:33:20 -070098void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
99 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700100 pending_pick *pp;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800101 grpc_connected_subchannel *selected;
Craig Tillera82950e2015-09-22 12:33:20 -0700102 gpr_mu_lock(&p->mu);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800103 selected = GET_SELECTED(p);
Craig Tillera14215a2015-07-17 17:21:08 -0700104 p->shutdown = 1;
Craig Tiller5795da72015-09-17 15:27:13 -0700105 pp = p->pending_picks;
106 p->pending_picks = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700107 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
108 GRPC_CHANNEL_FATAL_FAILURE, "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 Tiller48613042015-11-29 14:45:11 -0800113 } else {
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;
Craig Tiller69b093b2016-02-25 19:04:07 -0800122 grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800123 pp->pollset);
Craig Tiller6c396862016-01-28 13:53:40 -0800124 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, 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,
Craig Tillerb5585d42015-11-17 07:18:31 -0800131 grpc_connected_subchannel **target) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800132 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
133 pending_pick *pp;
134 gpr_mu_lock(&p->mu);
135 pp = p->pending_picks;
136 p->pending_picks = NULL;
137 while (pp != NULL) {
138 pending_pick *next = pp->next;
139 if (pp->target == target) {
Craig Tiller69b093b2016-02-25 19:04:07 -0800140 grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800141 pp->pollset);
Craig Tiller577c9b22015-11-02 14:11:15 -0800142 *target = NULL;
Craig Tiller6c396862016-01-28 13:53:40 -0800143 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
Craig Tiller577c9b22015-11-02 14:11:15 -0800144 gpr_free(pp);
145 } else {
146 pp->next = p->pending_picks;
147 p->pending_picks = pp;
148 }
149 pp = next;
150 }
151 gpr_mu_unlock(&p->mu);
152}
153
Craig Tillera82950e2015-09-22 12:33:20 -0700154static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700155 p->started_picking = 1;
156 p->checking_subchannel = 0;
157 p->checking_connectivity = GRPC_CHANNEL_IDLE;
Craig Tiller48613042015-11-29 14:45:11 -0800158 GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700159 grpc_subchannel_notify_on_state_change(
160 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800161 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800162 &p->connectivity_changed);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700163}
164
Craig Tillera82950e2015-09-22 12:33:20 -0700165void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
166 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
167 gpr_mu_lock(&p->mu);
168 if (!p->started_picking) {
169 start_picking(exec_ctx, p);
170 }
171 gpr_mu_unlock(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700172}
173
Craig Tiller577c9b22015-11-02 14:11:15 -0800174int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
Craig Tillerab33b482015-11-21 08:11:04 -0800175 grpc_metadata_batch *initial_metadata,
176 grpc_connected_subchannel **target, grpc_closure *on_complete) {
Craig Tillera82950e2015-09-22 12:33:20 -0700177 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller45724b32015-09-22 10:42:19 -0700178 pending_pick *pp;
Craig Tiller320bee02016-01-06 17:33:45 -0800179
180 /* Check atomically for a selected channel */
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800181 grpc_connected_subchannel *selected = GET_SELECTED(p);
182 if (selected != NULL) {
183 *target = selected;
184 return 1;
185 }
Craig Tiller320bee02016-01-06 17:33:45 -0800186
187 /* No subchannel selected yet, so acquire lock and then attempt again */
Craig Tillera82950e2015-09-22 12:33:20 -0700188 gpr_mu_lock(&p->mu);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800189 selected = GET_SELECTED(p);
190 if (selected) {
Craig Tillera82950e2015-09-22 12:33:20 -0700191 gpr_mu_unlock(&p->mu);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800192 *target = selected;
Craig Tiller577c9b22015-11-02 14:11:15 -0800193 return 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700194 } else {
195 if (!p->started_picking) {
196 start_picking(exec_ctx, p);
Craig Tiller45724b32015-09-22 10:42:19 -0700197 }
Craig Tiller69b093b2016-02-25 19:04:07 -0800198 grpc_pollset_set_add_pollset(exec_ctx, p->base.interested_parties, pollset);
Craig Tillera82950e2015-09-22 12:33:20 -0700199 pp = gpr_malloc(sizeof(*pp));
200 pp->next = p->pending_picks;
201 pp->pollset = pollset;
202 pp->target = target;
203 pp->on_complete = on_complete;
204 p->pending_picks = pp;
205 gpr_mu_unlock(&p->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800206 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700207 }
Craig Tiller45724b32015-09-22 10:42:19 -0700208}
209
Craig Tiller1f41b6b2015-10-09 15:07:02 -0700210static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800211 bool iomgr_success) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700212 pick_first_lb_policy *p = arg;
213 size_t i;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700214 size_t num_subchannels = p->num_subchannels;
215 grpc_subchannel **subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700216
217 gpr_mu_lock(&p->mu);
218 subchannels = p->subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700219 p->num_subchannels = 0;
220 p->subchannels = NULL;
221 gpr_mu_unlock(&p->mu);
Craig Tiller48613042015-11-29 14:45:11 -0800222 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700223
224 for (i = 0; i < num_subchannels; i++) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700225 GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
226 }
227
228 gpr_free(subchannels);
229}
230
Craig Tillera82950e2015-09-22 12:33:20 -0700231static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tiller6c396862016-01-28 13:53:40 -0800232 bool iomgr_success) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700233 pick_first_lb_policy *p = arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800234 grpc_subchannel *selected_subchannel;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700235 pending_pick *pp;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800236 grpc_connected_subchannel *selected;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700237
Craig Tillera82950e2015-09-22 12:33:20 -0700238 gpr_mu_lock(&p->mu);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700239
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800240 selected = GET_SELECTED(p);
241
Craig Tillera82950e2015-09-22 12:33:20 -0700242 if (p->shutdown) {
243 gpr_mu_unlock(&p->mu);
Craig Tiller48613042015-11-29 14:45:11 -0800244 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700245 return;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800246 } else if (selected != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800247 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
248 /* if the selected channel goes bad, we're done */
249 p->checking_connectivity = GRPC_CHANNEL_FATAL_FAILURE;
250 }
Craig Tillera82950e2015-09-22 12:33:20 -0700251 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
252 p->checking_connectivity, "selected_changed");
253 if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
Craig Tillerab33b482015-11-21 08:11:04 -0800254 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800255 exec_ctx, selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800256 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700257 } else {
Craig Tiller48613042015-11-29 14:45:11 -0800258 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700259 }
Craig Tillera82950e2015-09-22 12:33:20 -0700260 } else {
261 loop:
262 switch (p->checking_connectivity) {
263 case GRPC_CHANNEL_READY:
264 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
265 GRPC_CHANNEL_READY, "connecting_ready");
Craig Tillerb5585d42015-11-17 07:18:31 -0800266 selected_subchannel = p->subchannels[p->checking_subchannel];
Craig Tiller81afdda2016-01-11 17:09:18 -0800267 selected =
268 grpc_subchannel_get_connected_subchannel(selected_subchannel);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800269 GPR_ASSERT(selected != NULL);
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800270 GRPC_CONNECTED_SUBCHANNEL_REF(selected, "picked_first");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700271 /* drop the pick list: we are connected now */
Craig Tiller48613042015-11-29 14:45:11 -0800272 GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
Craig Tillerd9d474a2016-01-26 06:50:51 -0800273 gpr_atm_rel_store(&p->selected, (gpr_atm)selected);
Craig Tiller6c396862016-01-28 13:53:40 -0800274 grpc_exec_ctx_enqueue(
275 exec_ctx, grpc_closure_create(destroy_subchannels, p), true, NULL);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700276 /* update any calls that were waiting for a pick */
Craig Tillera82950e2015-09-22 12:33:20 -0700277 while ((pp = p->pending_picks)) {
278 p->pending_picks = pp->next;
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800279 *pp->target = selected;
Craig Tiller69b093b2016-02-25 19:04:07 -0800280 grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800281 pp->pollset);
Craig Tiller6c396862016-01-28 13:53:40 -0800282 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700283 gpr_free(pp);
284 }
Craig Tillerab33b482015-11-21 08:11:04 -0800285 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller69b093b2016-02-25 19:04:07 -0800286 exec_ctx, selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800287 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700288 break;
289 case GRPC_CHANNEL_TRANSIENT_FAILURE:
290 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
291 GRPC_CHANNEL_TRANSIENT_FAILURE,
292 "connecting_transient_failure");
Craig Tillera82950e2015-09-22 12:33:20 -0700293 p->checking_subchannel =
294 (p->checking_subchannel + 1) % p->num_subchannels;
295 p->checking_connectivity = grpc_subchannel_check_connectivity(
296 p->subchannels[p->checking_subchannel]);
Craig Tillera82950e2015-09-22 12:33:20 -0700297 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
298 grpc_subchannel_notify_on_state_change(
299 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800300 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800301 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700302 } else {
303 goto loop;
304 }
305 break;
306 case GRPC_CHANNEL_CONNECTING:
307 case GRPC_CHANNEL_IDLE:
308 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
309 GRPC_CHANNEL_CONNECTING,
310 "connecting_changed");
311 grpc_subchannel_notify_on_state_change(
312 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800313 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800314 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700315 break;
316 case GRPC_CHANNEL_FATAL_FAILURE:
Craig Tillera82950e2015-09-22 12:33:20 -0700317 p->num_subchannels--;
Craig Tiller86c99582015-11-25 15:22:26 -0800318 GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
319 p->subchannels[p->num_subchannels]);
Craig Tillera82950e2015-09-22 12:33:20 -0700320 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
321 "pick_first");
322 if (p->num_subchannels == 0) {
323 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
324 GRPC_CHANNEL_FATAL_FAILURE,
325 "no_more_channels");
326 while ((pp = p->pending_picks)) {
327 p->pending_picks = pp->next;
328 *pp->target = NULL;
Craig Tiller6c396862016-01-28 13:53:40 -0800329 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, true, NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700330 gpr_free(pp);
331 }
Craig Tiller1d881fb2015-12-01 07:39:04 -0800332 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
333 "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700334 } else {
335 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
336 GRPC_CHANNEL_TRANSIENT_FAILURE,
337 "subchannel_failed");
338 p->checking_subchannel %= p->num_subchannels;
339 p->checking_connectivity = grpc_subchannel_check_connectivity(
340 p->subchannels[p->checking_subchannel]);
Craig Tillera82950e2015-09-22 12:33:20 -0700341 goto loop;
342 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700343 }
Craig Tillera82950e2015-09-22 12:33:20 -0700344 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700345
Craig Tillera82950e2015-09-22 12:33:20 -0700346 gpr_mu_unlock(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700347}
348
Craig Tillera82950e2015-09-22 12:33:20 -0700349static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
350 grpc_lb_policy *pol) {
351 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerc7b5f762015-06-27 11:48:42 -0700352 grpc_connectivity_state st;
Craig Tillera82950e2015-09-22 12:33:20 -0700353 gpr_mu_lock(&p->mu);
354 st = grpc_connectivity_state_check(&p->state_tracker);
355 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700356 return st;
357}
358
Craig Tillera82950e2015-09-22 12:33:20 -0700359void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
360 grpc_connectivity_state *current,
361 grpc_closure *notify) {
362 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
363 gpr_mu_lock(&p->mu);
364 grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
365 current, notify);
366 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700367}
368
Craig Tillere2c62372015-12-07 16:11:03 -0800369void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
370 grpc_closure *closure) {
Craig Tiller28bf8912015-12-07 16:07:04 -0800371 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller093193e2016-01-07 07:14:44 -0800372 grpc_connected_subchannel *selected = GET_SELECTED(p);
373 if (selected) {
374 grpc_connected_subchannel_ping(exec_ctx, selected, closure);
Craig Tiller28bf8912015-12-07 16:07:04 -0800375 } else {
Craig Tiller6c396862016-01-28 13:53:40 -0800376 grpc_exec_ctx_enqueue(exec_ctx, closure, false, NULL);
Craig Tiller28bf8912015-12-07 16:07:04 -0800377 }
Craig Tiller28bf8912015-12-07 16:07:04 -0800378}
379
Craig Tillereb3b12e2015-06-26 14:42:49 -0700380static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
Craig Tillerf40df232016-03-25 13:38:14 -0700381 pf_destroy,
382 pf_shutdown,
383 pf_pick,
384 pf_cancel_pick,
385 pf_ping_one,
386 pf_exit_idle,
387 pf_check_connectivity,
388 pf_notify_on_state_change};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700389
Craig Tillera82950e2015-09-22 12:33:20 -0700390static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700391
Craig Tillera82950e2015-09-22 12:33:20 -0700392static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700393
Craig Tillera82950e2015-09-22 12:33:20 -0700394static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
395 grpc_lb_policy_args *args) {
Craig Tiller1e55bd42016-03-11 09:47:43 -0800396 if (args->num_subchannels == 0) return NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700397 pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
Craig Tillera82950e2015-09-22 12:33:20 -0700398 memset(p, 0, sizeof(*p));
399 grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
400 p->subchannels =
401 gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
David Garcia Quintasc7705c72015-09-09 17:21:11 -0700402 p->num_subchannels = args->num_subchannels;
Craig Tillera82950e2015-09-22 12:33:20 -0700403 grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
404 "pick_first");
405 memcpy(p->subchannels, args->subchannels,
406 sizeof(grpc_subchannel *) * args->num_subchannels);
407 grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
408 gpr_mu_init(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700409 return &p->base;
410}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700411
412static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700413 pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
414 "pick_first"};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700415
416static grpc_lb_policy_factory pick_first_lb_policy_factory = {
Craig Tillera82950e2015-09-22 12:33:20 -0700417 &pick_first_factory_vtable};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700418
Craig Tillera82950e2015-09-22 12:33:20 -0700419grpc_lb_policy_factory *grpc_pick_first_lb_factory_create() {
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700420 return &pick_first_lb_policy_factory;
421}