blob: 501cb6d94dff2558b082c2df802d0bc0c82aad97 [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>
Mark D. Roth5bd7be02016-10-21 14:19:50 -070037
Mark D. Roth2137cd82016-09-14 09:04:00 -070038#include "src/core/ext/client_channel/lb_policy_registry.h"
Mark D. Roth0748f392017-01-13 09:22:44 -080039#include "src/core/ext/client_channel/subchannel.h"
Mark D. Roth557c9902016-10-24 11:12:05 -070040#include "src/core/lib/channel/channel_args.h"
Craig Tiller2400bf52017-02-09 16:25:19 -080041#include "src/core/lib/iomgr/combiner.h"
Mark D. Roth0748f392017-01-13 09:22:44 -080042#include "src/core/lib/iomgr/sockaddr_utils.h"
Craig Tiller9533d042016-03-25 17:11:06 -070043#include "src/core/lib/transport/connectivity_state.h"
Craig Tillereb3b12e2015-06-26 14:42:49 -070044
Craig Tillera82950e2015-09-22 12:33:20 -070045typedef struct pending_pick {
Craig Tillereb3b12e2015-06-26 14:42:49 -070046 struct pending_pick *next;
Craig Tiller8c0d96f2016-03-11 14:27:52 -080047 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -080048 grpc_connected_subchannel **target;
Craig Tiller33825112015-09-18 07:44:19 -070049 grpc_closure *on_complete;
Craig Tillereb3b12e2015-06-26 14:42:49 -070050} pending_pick;
51
Craig Tillera82950e2015-09-22 12:33:20 -070052typedef struct {
Craig Tillereb3b12e2015-06-26 14:42:49 -070053 /** base policy: must be first */
54 grpc_lb_policy base;
Craig Tillereb3b12e2015-06-26 14:42:49 -070055 /** all our subchannels */
56 grpc_subchannel **subchannels;
57 size_t num_subchannels;
58
Craig Tiller33825112015-09-18 07:44:19 -070059 grpc_closure connectivity_changed;
Craig Tillereb3b12e2015-06-26 14:42:49 -070060
Craig Tiller2400bf52017-02-09 16:25:19 -080061 /** remaining members are protected by the combiner */
Craig Tiller320bee02016-01-06 17:33:45 -080062
Craig Tiller46dd7902017-02-23 09:42:16 -080063 /** the selected channel */
Craig Tiller2400bf52017-02-09 16:25:19 -080064 grpc_connected_subchannel *selected;
65
Craig Tillereb3b12e2015-06-26 14:42:49 -070066 /** have we started picking? */
67 int started_picking;
Craig Tillera14215a2015-07-17 17:21:08 -070068 /** are we shut down? */
69 int shutdown;
Craig Tillereb3b12e2015-06-26 14:42:49 -070070 /** which subchannel are we watching? */
71 size_t checking_subchannel;
72 /** what is the connectivity of that channel? */
73 grpc_connectivity_state checking_connectivity;
74 /** list of picks that are waiting on connectivity */
75 pending_pick *pending_picks;
Craig Tillerc7b5f762015-06-27 11:48:42 -070076
77 /** our connectivity state tracker */
78 grpc_connectivity_state_tracker state_tracker;
Craig Tillereb3b12e2015-06-26 14:42:49 -070079} pick_first_lb_policy;
80
Craig Tillerfb433852016-03-29 08:51:07 -070081static void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -070082 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
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 Tiller2400bf52017-02-09 16:25:19 -080088 if (p->selected != NULL) {
89 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->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);
Craig Tillera82950e2015-09-22 12:33:20 -070093 gpr_free(p);
Craig Tillereb3b12e2015-06-26 14:42:49 -070094}
95
Craig Tiller2400bf52017-02-09 16:25:19 -080096static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -070097 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerd2cc4592015-07-01 07:50:47 -070098 pending_pick *pp;
Craig Tillera14215a2015-07-17 17:21:08 -070099 p->shutdown = 1;
Craig Tiller5795da72015-09-17 15:27:13 -0700100 pp = p->pending_picks;
101 p->pending_picks = NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700102 grpc_connectivity_state_set(
Craig Tillerd925c932016-06-06 08:38:50 -0700103 exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700104 GRPC_ERROR_CREATE("Channel shutdown"), "shutdown");
Craig Tillerf036a642015-12-01 17:00:40 -0800105 /* cancel subscription */
Craig Tiller2400bf52017-02-09 16:25:19 -0800106 if (p->selected != NULL) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800107 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller2400bf52017-02-09 16:25:19 -0800108 exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
Craig Tillere2b86c72016-04-14 17:34:01 -0700109 } else if (p->num_subchannels > 0) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800110 grpc_subchannel_notify_on_state_change(
111 exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
112 &p->connectivity_changed);
Craig Tiller48613042015-11-29 14:45:11 -0800113 }
Craig Tillera82950e2015-09-22 12:33:20 -0700114 while (pp != NULL) {
115 pending_pick *next = pp->next;
116 *pp->target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800117 grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700118 gpr_free(pp);
119 pp = next;
120 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700121}
122
Craig Tiller2400bf52017-02-09 16:25:19 -0800123static void pf_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
124 grpc_connected_subchannel **target,
125 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800126 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
127 pending_pick *pp;
Craig Tiller577c9b22015-11-02 14:11:15 -0800128 pp = p->pending_picks;
129 p->pending_picks = NULL;
130 while (pp != NULL) {
131 pending_pick *next = pp->next;
132 if (pp->target == target) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800133 *target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800134 grpc_closure_sched(
Mark D. Roth932b10c2016-09-09 08:44:30 -0700135 exec_ctx, pp->on_complete,
Craig Tiller91031da2016-12-28 15:44:25 -0800136 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800137 gpr_free(pp);
138 } else {
139 pp->next = p->pending_picks;
140 p->pending_picks = pp;
141 }
142 pp = next;
143 }
Mark D. Roth5f844002016-09-08 08:20:53 -0700144 GRPC_ERROR_UNREF(error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800145}
146
Craig Tiller2400bf52017-02-09 16:25:19 -0800147static void pf_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
148 uint32_t initial_metadata_flags_mask,
149 uint32_t initial_metadata_flags_eq,
150 grpc_error *error) {
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800151 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
152 pending_pick *pp;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800153 pp = p->pending_picks;
154 p->pending_picks = NULL;
155 while (pp != NULL) {
156 pending_pick *next = pp->next;
157 if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
158 initial_metadata_flags_eq) {
Craig Tiller91031da2016-12-28 15:44:25 -0800159 grpc_closure_sched(
Mark D. Roth58f52b72016-09-09 13:55:18 -0700160 exec_ctx, pp->on_complete,
Craig Tiller91031da2016-12-28 15:44:25 -0800161 GRPC_ERROR_CREATE_REFERENCING("Pick Cancelled", &error, 1));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800162 gpr_free(pp);
163 } else {
164 pp->next = p->pending_picks;
165 p->pending_picks = pp;
166 }
167 pp = next;
168 }
Mark D. Rothe65ff112016-09-09 13:48:38 -0700169 GRPC_ERROR_UNREF(error);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800170}
171
Craig Tillera82950e2015-09-22 12:33:20 -0700172static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700173 p->started_picking = 1;
174 p->checking_subchannel = 0;
175 p->checking_connectivity = GRPC_CHANNEL_IDLE;
Craig Tiller48613042015-11-29 14:45:11 -0800176 GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700177 grpc_subchannel_notify_on_state_change(
178 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800179 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800180 &p->connectivity_changed);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700181}
182
Craig Tiller2400bf52017-02-09 16:25:19 -0800183static void pf_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -0700184 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillera82950e2015-09-22 12:33:20 -0700185 if (!p->started_picking) {
186 start_picking(exec_ctx, p);
187 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700188}
189
Craig Tiller2400bf52017-02-09 16:25:19 -0800190static int pf_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
191 const grpc_lb_policy_pick_args *pick_args,
192 grpc_connected_subchannel **target, void **user_data,
193 grpc_closure *on_complete) {
Craig Tillera82950e2015-09-22 12:33:20 -0700194 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller45724b32015-09-22 10:42:19 -0700195 pending_pick *pp;
Craig Tiller320bee02016-01-06 17:33:45 -0800196
197 /* Check atomically for a selected channel */
Craig Tiller2400bf52017-02-09 16:25:19 -0800198 if (p->selected != NULL) {
199 *target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800200 return 1;
201 }
Craig Tiller320bee02016-01-06 17:33:45 -0800202
Craig Tiller46dd7902017-02-23 09:42:16 -0800203 /* No subchannel selected yet, so try again */
Craig Tiller2400bf52017-02-09 16:25:19 -0800204 if (!p->started_picking) {
205 start_picking(exec_ctx, p);
Craig Tillera82950e2015-09-22 12:33:20 -0700206 }
Craig Tiller2400bf52017-02-09 16:25:19 -0800207 pp = gpr_malloc(sizeof(*pp));
208 pp->next = p->pending_picks;
209 pp->target = target;
210 pp->initial_metadata_flags = pick_args->initial_metadata_flags;
211 pp->on_complete = on_complete;
212 p->pending_picks = pp;
213 return 0;
Craig Tiller45724b32015-09-22 10:42:19 -0700214}
215
Craig Tiller2400bf52017-02-09 16:25:19 -0800216static void destroy_subchannels_locked(grpc_exec_ctx *exec_ctx,
217 pick_first_lb_policy *p) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700218 size_t i;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700219 size_t num_subchannels = p->num_subchannels;
220 grpc_subchannel **subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700221
Craig Tillerb09d84d2015-10-06 09:12:16 -0700222 subchannels = p->subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700223 p->num_subchannels = 0;
224 p->subchannels = NULL;
Craig Tiller48613042015-11-29 14:45:11 -0800225 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700226
227 for (i = 0; i < num_subchannels; i++) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700228 GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
229 }
230
231 gpr_free(subchannels);
232}
233
Craig Tiller2400bf52017-02-09 16:25:19 -0800234static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
235 grpc_error *error) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700236 pick_first_lb_policy *p = arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800237 grpc_subchannel *selected_subchannel;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700238 pending_pick *pp;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700239
Craig Tillerf707d622016-05-06 14:26:12 -0700240 GRPC_ERROR_REF(error);
Craig Tiller804ff712016-05-05 16:25:40 -0700241
Craig Tillera82950e2015-09-22 12:33:20 -0700242 if (p->shutdown) {
Craig Tiller48613042015-11-29 14:45:11 -0800243 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tillerae125932016-05-13 16:34:29 -0700244 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700245 return;
Craig Tiller2400bf52017-02-09 16:25:19 -0800246 } else if (p->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 */
Craig Tiller48ed92e2016-06-02 11:07:12 -0700249 p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
Craig Tillercb2609f2015-11-24 17:19:19 -0800250 }
Craig Tillera82950e2015-09-22 12:33:20 -0700251 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
Craig Tillerf707d622016-05-06 14:26:12 -0700252 p->checking_connectivity, GRPC_ERROR_REF(error),
Craig Tiller804ff712016-05-05 16:25:40 -0700253 "selected_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700254 if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillerab33b482015-11-21 08:11:04 -0800255 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller2400bf52017-02-09 16:25:19 -0800256 exec_ctx, p->selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800257 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700258 } else {
Craig Tiller48613042015-11-29 14:45:11 -0800259 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700260 }
Craig Tillera82950e2015-09-22 12:33:20 -0700261 } else {
262 loop:
263 switch (p->checking_connectivity) {
David Garcia Quintasea6689d2016-11-08 09:46:41 -0800264 case GRPC_CHANNEL_INIT:
Jan Tattermuschb0fb2d22016-11-16 14:04:05 +0100265 GPR_UNREACHABLE_CODE(return );
Craig Tillera82950e2015-09-22 12:33:20 -0700266 case GRPC_CHANNEL_READY:
267 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
Craig Tiller804ff712016-05-05 16:25:40 -0700268 GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
269 "connecting_ready");
Craig Tillerb5585d42015-11-17 07:18:31 -0800270 selected_subchannel = p->subchannels[p->checking_subchannel];
Craig Tiller2400bf52017-02-09 16:25:19 -0800271 p->selected = GRPC_CONNECTED_SUBCHANNEL_REF(
272 grpc_subchannel_get_connected_subchannel(selected_subchannel),
273 "picked_first");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700274 /* drop the pick list: we are connected now */
Craig Tiller48613042015-11-29 14:45:11 -0800275 GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
Craig Tiller2400bf52017-02-09 16:25:19 -0800276 destroy_subchannels_locked(exec_ctx, p);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700277 /* update any calls that were waiting for a pick */
Craig Tillera82950e2015-09-22 12:33:20 -0700278 while ((pp = p->pending_picks)) {
279 p->pending_picks = pp->next;
Craig Tiller2400bf52017-02-09 16:25:19 -0800280 *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
Craig Tiller91031da2016-12-28 15:44:25 -0800281 grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700282 gpr_free(pp);
283 }
Craig Tillerab33b482015-11-21 08:11:04 -0800284 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller2400bf52017-02-09 16:25:19 -0800285 exec_ctx, p->selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800286 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700287 break;
288 case GRPC_CHANNEL_TRANSIENT_FAILURE:
Craig Tillera82950e2015-09-22 12:33:20 -0700289 p->checking_subchannel =
290 (p->checking_subchannel + 1) % p->num_subchannels;
Craig Tiller131b6de2016-03-31 17:05:28 -0700291 if (p->checking_subchannel == 0) {
292 /* only trigger transient failure when we've tried all alternatives */
Craig Tiller804ff712016-05-05 16:25:40 -0700293 grpc_connectivity_state_set(
294 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tillerf707d622016-05-06 14:26:12 -0700295 GRPC_ERROR_REF(error), "connecting_transient_failure");
Craig Tiller131b6de2016-03-31 17:05:28 -0700296 }
Craig Tillerf707d622016-05-06 14:26:12 -0700297 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700298 p->checking_connectivity = grpc_subchannel_check_connectivity(
Craig Tiller804ff712016-05-05 16:25:40 -0700299 p->subchannels[p->checking_subchannel], &error);
Craig Tillera82950e2015-09-22 12:33:20 -0700300 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
301 grpc_subchannel_notify_on_state_change(
302 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800303 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800304 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700305 } else {
306 goto loop;
307 }
308 break;
309 case GRPC_CHANNEL_CONNECTING:
310 case GRPC_CHANNEL_IDLE:
Craig Tiller804ff712016-05-05 16:25:40 -0700311 grpc_connectivity_state_set(
312 exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING,
Craig Tillerf707d622016-05-06 14:26:12 -0700313 GRPC_ERROR_REF(error), "connecting_changed");
Craig Tillera82950e2015-09-22 12:33:20 -0700314 grpc_subchannel_notify_on_state_change(
315 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800316 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800317 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700318 break;
Craig Tiller48ed92e2016-06-02 11:07:12 -0700319 case GRPC_CHANNEL_SHUTDOWN:
Craig Tillera82950e2015-09-22 12:33:20 -0700320 p->num_subchannels--;
Craig Tiller86c99582015-11-25 15:22:26 -0800321 GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
322 p->subchannels[p->num_subchannels]);
Craig Tillera82950e2015-09-22 12:33:20 -0700323 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
324 "pick_first");
325 if (p->num_subchannels == 0) {
Craig Tiller804ff712016-05-05 16:25:40 -0700326 grpc_connectivity_state_set(
Craig Tillerd925c932016-06-06 08:38:50 -0700327 exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller804ff712016-05-05 16:25:40 -0700328 GRPC_ERROR_CREATE_REFERENCING("Pick first exhausted channels",
329 &error, 1),
330 "no_more_channels");
Craig Tillera82950e2015-09-22 12:33:20 -0700331 while ((pp = p->pending_picks)) {
332 p->pending_picks = pp->next;
333 *pp->target = NULL;
Craig Tiller91031da2016-12-28 15:44:25 -0800334 grpc_closure_sched(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700335 gpr_free(pp);
336 }
Craig Tiller1d881fb2015-12-01 07:39:04 -0800337 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
338 "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700339 } else {
Craig Tiller804ff712016-05-05 16:25:40 -0700340 grpc_connectivity_state_set(
341 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tillerf707d622016-05-06 14:26:12 -0700342 GRPC_ERROR_REF(error), "subchannel_failed");
Craig Tillera82950e2015-09-22 12:33:20 -0700343 p->checking_subchannel %= p->num_subchannels;
Craig Tillerf707d622016-05-06 14:26:12 -0700344 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700345 p->checking_connectivity = grpc_subchannel_check_connectivity(
Craig Tiller804ff712016-05-05 16:25:40 -0700346 p->subchannels[p->checking_subchannel], &error);
Craig Tillera82950e2015-09-22 12:33:20 -0700347 goto loop;
348 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700349 }
Craig Tillera82950e2015-09-22 12:33:20 -0700350 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700351
Craig Tillerf707d622016-05-06 14:26:12 -0700352 GRPC_ERROR_UNREF(error);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700353}
354
Craig Tiller2400bf52017-02-09 16:25:19 -0800355static grpc_connectivity_state pf_check_connectivity_locked(
356 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) {
Craig Tillera82950e2015-09-22 12:33:20 -0700357 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller2400bf52017-02-09 16:25:19 -0800358 return grpc_connectivity_state_get(&p->state_tracker, error);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700359}
360
Craig Tiller2400bf52017-02-09 16:25:19 -0800361static void pf_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
362 grpc_lb_policy *pol,
363 grpc_connectivity_state *current,
364 grpc_closure *notify) {
Craig Tillera82950e2015-09-22 12:33:20 -0700365 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillera82950e2015-09-22 12:33:20 -0700366 grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
367 current, notify);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700368}
369
Craig Tiller2400bf52017-02-09 16:25:19 -0800370static void pf_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
371 grpc_closure *closure) {
Craig Tiller28bf8912015-12-07 16:07:04 -0800372 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller2400bf52017-02-09 16:25:19 -0800373 if (p->selected) {
374 grpc_connected_subchannel_ping(exec_ctx, p->selected, closure);
Craig Tiller28bf8912015-12-07 16:07:04 -0800375 } else {
Craig Tiller91031da2016-12-28 15:44:25 -0800376 grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_CREATE("Not connected"));
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 Tiller2400bf52017-02-09 16:25:19 -0800381 pf_destroy,
382 pf_shutdown_locked,
383 pf_pick_locked,
384 pf_cancel_pick_locked,
385 pf_cancel_picks_locked,
386 pf_ping_one_locked,
387 pf_exit_idle_locked,
388 pf_check_connectivity_locked,
389 pf_notify_on_state_change_locked};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700390
Craig Tillera82950e2015-09-22 12:33:20 -0700391static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700392
Craig Tillera82950e2015-09-22 12:33:20 -0700393static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700394
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700395static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
396 grpc_lb_policy_factory *factory,
Craig Tillera82950e2015-09-22 12:33:20 -0700397 grpc_lb_policy_args *args) {
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700398 GPR_ASSERT(args->client_channel_factory != NULL);
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700399
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700400 /* Find the number of backend addresses. We ignore balancer
401 * addresses, since we don't know how to handle them. */
Mark D. Roth201db7d2016-12-12 09:36:02 -0800402 const grpc_arg *arg =
403 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700404 GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
Mark D. Roth557c9902016-10-24 11:12:05 -0700405 grpc_lb_addresses *addresses = arg->value.pointer.p;
Mark D. Rothf655c852016-09-06 10:40:38 -0700406 size_t num_addrs = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700407 for (size_t i = 0; i < addresses->num_addresses; i++) {
408 if (!addresses->addresses[i].is_balancer) ++num_addrs;
Mark D. Rothf655c852016-09-06 10:40:38 -0700409 }
410 if (num_addrs == 0) return NULL;
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700411
Craig Tillera82950e2015-09-22 12:33:20 -0700412 pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
Craig Tillera82950e2015-09-22 12:33:20 -0700413 memset(p, 0, sizeof(*p));
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700414
Mark D. Roth989cdcd2016-09-06 13:28:28 -0700415 p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * num_addrs);
Mark D. Rothf655c852016-09-06 10:40:38 -0700416 memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700417 grpc_subchannel_args sc_args;
418 size_t subchannel_idx = 0;
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700419 for (size_t i = 0; i < addresses->num_addresses; i++) {
Mark D. Rothe011b1e2016-09-07 08:28:00 -0700420 /* Skip balancer addresses, since we only know how to handle backends. */
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700421 if (addresses->addresses[i].is_balancer) continue;
Mark D. Rothf655c852016-09-06 10:40:38 -0700422
Mark D. Roth5bd7be02016-10-21 14:19:50 -0700423 if (addresses->addresses[i].user_data != NULL) {
David Garcia Quintas5ebb7af2016-09-15 10:02:16 -0700424 gpr_log(GPR_ERROR,
425 "This LB policy doesn't support user data. It will be ignored");
426 }
David Garcia Quintasf47d6fb2016-09-14 12:59:17 -0700427
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700428 memset(&sc_args, 0, sizeof(grpc_subchannel_args));
Mark D. Rothdf8f1222017-01-13 22:59:39 +0000429 grpc_arg addr_arg =
430 grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
Mark D. Roth0748f392017-01-13 09:22:44 -0800431 grpc_channel_args *new_args =
432 grpc_channel_args_copy_and_add(args->args, &addr_arg, 1);
433 gpr_free(addr_arg.value.string);
434 sc_args.args = new_args;
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700435 grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
436 exec_ctx, args->client_channel_factory, &sc_args);
Mark D. Roth0748f392017-01-13 09:22:44 -0800437 grpc_channel_args_destroy(exec_ctx, new_args);
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700438
439 if (subchannel != NULL) {
440 p->subchannels[subchannel_idx++] = subchannel;
441 }
442 }
443 if (subchannel_idx == 0) {
444 gpr_free(p->subchannels);
445 gpr_free(p);
446 return NULL;
447 }
448 p->num_subchannels = subchannel_idx;
449
Craig Tiller2400bf52017-02-09 16:25:19 -0800450 grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
451 grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed_locked, p,
452 grpc_combiner_scheduler(args->combiner, false));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700453 return &p->base;
454}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700455
456static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700457 pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
458 "pick_first"};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700459
460static grpc_lb_policy_factory pick_first_lb_policy_factory = {
Craig Tillera82950e2015-09-22 12:33:20 -0700461 &pick_first_factory_vtable};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700462
Craig Tillerfb433852016-03-29 08:51:07 -0700463static grpc_lb_policy_factory *pick_first_lb_factory_create() {
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700464 return &pick_first_lb_policy_factory;
465}
Craig Tillerfb433852016-03-29 08:51:07 -0700466
467/* Plugin registration */
468
469void grpc_lb_policy_pick_first_init() {
Craig Tiller3113ef42016-03-29 09:03:14 -0700470 grpc_register_lb_policy(pick_first_lb_factory_create());
Craig Tillerfb433852016-03-29 08:51:07 -0700471}
472
473void grpc_lb_policy_pick_first_shutdown() {}