blob: b07fc3b720bf26432e08e65aeaee6a9f414733ac [file] [log] [blame]
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070016 *
17 */
18
Craig Tillereb3b12e2015-06-26 14:42:49 -070019#include <string.h>
20
21#include <grpc/support/alloc.h>
Mark D. Roth5bd7be02016-10-21 14:19:50 -070022
Craig Tiller9eb0fde2017-03-31 16:59:30 -070023#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
24#include "src/core/ext/filters/client_channel/subchannel.h"
David Garcia Quintas87d5a312017-06-06 19:45:58 -070025#include "src/core/ext/filters/client_channel/subchannel_index.h"
Mark D. Roth557c9902016-10-24 11:12:05 -070026#include "src/core/lib/channel/channel_args.h"
Craig Tiller2400bf52017-02-09 16:25:19 -080027#include "src/core/lib/iomgr/combiner.h"
Mark D. Roth0748f392017-01-13 09:22:44 -080028#include "src/core/lib/iomgr/sockaddr_utils.h"
Craig Tiller9533d042016-03-25 17:11:06 -070029#include "src/core/lib/transport/connectivity_state.h"
Craig Tillereb3b12e2015-06-26 14:42:49 -070030
ncteisen7712c7c2017-07-12 23:11:27 -070031grpc_tracer_flag grpc_lb_pick_first_trace =
32 GRPC_TRACER_INITIALIZER(false, "pick_first");
David Garcia Quintas87d5a312017-06-06 19:45:58 -070033
Craig Tillera82950e2015-09-22 12:33:20 -070034typedef struct pending_pick {
Craig Tillereb3b12e2015-06-26 14:42:49 -070035 struct pending_pick *next;
Craig Tiller8c0d96f2016-03-11 14:27:52 -080036 uint32_t initial_metadata_flags;
Craig Tillerb5585d42015-11-17 07:18:31 -080037 grpc_connected_subchannel **target;
Craig Tiller33825112015-09-18 07:44:19 -070038 grpc_closure *on_complete;
Craig Tillereb3b12e2015-06-26 14:42:49 -070039} pending_pick;
40
Craig Tillera82950e2015-09-22 12:33:20 -070041typedef struct {
Craig Tillereb3b12e2015-06-26 14:42:49 -070042 /** base policy: must be first */
43 grpc_lb_policy base;
Craig Tillereb3b12e2015-06-26 14:42:49 -070044 /** all our subchannels */
45 grpc_subchannel **subchannels;
David Garcia Quintas87d5a312017-06-06 19:45:58 -070046 grpc_subchannel **new_subchannels;
Craig Tillereb3b12e2015-06-26 14:42:49 -070047 size_t num_subchannels;
David Garcia Quintas87d5a312017-06-06 19:45:58 -070048 size_t num_new_subchannels;
Craig Tillereb3b12e2015-06-26 14:42:49 -070049
Craig Tiller33825112015-09-18 07:44:19 -070050 grpc_closure connectivity_changed;
Craig Tillereb3b12e2015-06-26 14:42:49 -070051
Craig Tiller2400bf52017-02-09 16:25:19 -080052 /** remaining members are protected by the combiner */
Craig Tiller320bee02016-01-06 17:33:45 -080053
Craig Tiller46dd7902017-02-23 09:42:16 -080054 /** the selected channel */
Craig Tiller2400bf52017-02-09 16:25:19 -080055 grpc_connected_subchannel *selected;
56
David Garcia Quintas87d5a312017-06-06 19:45:58 -070057 /** the subchannel key for \a selected, or NULL if \a selected not set */
58 const grpc_subchannel_key *selected_key;
59
Craig Tillereb3b12e2015-06-26 14:42:49 -070060 /** have we started picking? */
David Garcia Quintas87d5a312017-06-06 19:45:58 -070061 bool started_picking;
Craig Tillera14215a2015-07-17 17:21:08 -070062 /** are we shut down? */
David Garcia Quintas87d5a312017-06-06 19:45:58 -070063 bool shutdown;
64 /** are we updating the selected subchannel? */
65 bool updating_selected;
66 /** are we updating the subchannel candidates? */
67 bool updating_subchannels;
68 /** args from the latest update received while already updating, or NULL */
69 grpc_lb_policy_args *pending_update_args;
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 Tillera82950e2015-09-22 12:33:20 -070083 GPR_ASSERT(p->pending_picks == NULL);
David Garcia Quintas87d5a312017-06-06 19:45:58 -070084 for (size_t i = 0; i < p->num_subchannels; i++) {
85 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first_destroy");
Craig Tillera82950e2015-09-22 12:33:20 -070086 }
Craig Tiller2400bf52017-02-09 16:25:19 -080087 if (p->selected != NULL) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -070088 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected,
89 "picked_first_destroy");
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);
Juanli Shen6502ecc2017-09-13 13:10:54 -070092 grpc_subchannel_index_unref();
David Garcia Quintas87d5a312017-06-06 19:45:58 -070093 if (p->pending_update_args != NULL) {
94 grpc_channel_args_destroy(exec_ctx, p->pending_update_args->args);
95 gpr_free(p->pending_update_args);
96 }
Craig Tillera82950e2015-09-22 12:33:20 -070097 gpr_free(p->subchannels);
David Garcia Quintas87d5a312017-06-06 19:45:58 -070098 gpr_free(p->new_subchannels);
Craig Tillera82950e2015-09-22 12:33:20 -070099 gpr_free(p);
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700100 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
101 gpr_log(GPR_DEBUG, "Pick First %p destroyed.", (void *)p);
102 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700103}
104
Craig Tiller2400bf52017-02-09 16:25:19 -0800105static void pf_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -0700106 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700107 pending_pick *pp;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700108 p->shutdown = true;
Craig Tiller5795da72015-09-17 15:27:13 -0700109 pp = p->pending_picks;
110 p->pending_picks = NULL;
Craig Tiller804ff712016-05-05 16:25:40 -0700111 grpc_connectivity_state_set(
Craig Tillerd925c932016-06-06 08:38:50 -0700112 exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700113 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown"), "shutdown");
Craig Tillerf036a642015-12-01 17:00:40 -0800114 /* cancel subscription */
Craig Tiller2400bf52017-02-09 16:25:19 -0800115 if (p->selected != NULL) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800116 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller2400bf52017-02-09 16:25:19 -0800117 exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700118 } else if (p->num_subchannels > 0 && p->started_picking) {
Craig Tiller1d881fb2015-12-01 07:39:04 -0800119 grpc_subchannel_notify_on_state_change(
120 exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
121 &p->connectivity_changed);
Craig Tiller48613042015-11-29 14:45:11 -0800122 }
Craig Tillera82950e2015-09-22 12:33:20 -0700123 while (pp != NULL) {
124 pending_pick *next = pp->next;
125 *pp->target = NULL;
ncteisen274bbbe2017-06-08 14:57:11 -0700126 GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700127 gpr_free(pp);
128 pp = next;
129 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700130}
131
Craig Tiller2400bf52017-02-09 16:25:19 -0800132static void pf_cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
133 grpc_connected_subchannel **target,
134 grpc_error *error) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800135 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
136 pending_pick *pp;
Craig Tiller577c9b22015-11-02 14:11:15 -0800137 pp = p->pending_picks;
138 p->pending_picks = NULL;
139 while (pp != NULL) {
140 pending_pick *next = pp->next;
141 if (pp->target == target) {
Craig Tiller577c9b22015-11-02 14:11:15 -0800142 *target = NULL;
ncteisen274bbbe2017-06-08 14:57:11 -0700143 GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete,
ncteisen4b36a3d2017-03-13 19:08:06 -0700144 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
145 "Pick Cancelled", &error, 1));
Craig Tiller577c9b22015-11-02 14:11:15 -0800146 gpr_free(pp);
147 } else {
148 pp->next = p->pending_picks;
149 p->pending_picks = pp;
150 }
151 pp = next;
152 }
Mark D. Roth5f844002016-09-08 08:20:53 -0700153 GRPC_ERROR_UNREF(error);
Craig Tiller577c9b22015-11-02 14:11:15 -0800154}
155
Craig Tiller2400bf52017-02-09 16:25:19 -0800156static void pf_cancel_picks_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
157 uint32_t initial_metadata_flags_mask,
158 uint32_t initial_metadata_flags_eq,
159 grpc_error *error) {
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800160 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
161 pending_pick *pp;
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800162 pp = p->pending_picks;
163 p->pending_picks = NULL;
164 while (pp != NULL) {
165 pending_pick *next = pp->next;
166 if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
167 initial_metadata_flags_eq) {
ncteisen274bbbe2017-06-08 14:57:11 -0700168 GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete,
ncteisen4b36a3d2017-03-13 19:08:06 -0700169 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
170 "Pick Cancelled", &error, 1));
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800171 gpr_free(pp);
172 } else {
173 pp->next = p->pending_picks;
174 p->pending_picks = pp;
175 }
176 pp = next;
177 }
Mark D. Rothe65ff112016-09-09 13:48:38 -0700178 GRPC_ERROR_UNREF(error);
Craig Tiller8c0d96f2016-03-11 14:27:52 -0800179}
180
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700181static void start_picking_locked(grpc_exec_ctx *exec_ctx,
182 pick_first_lb_policy *p) {
183 p->started_picking = true;
184 if (p->subchannels != NULL) {
185 GPR_ASSERT(p->num_subchannels > 0);
186 p->checking_subchannel = 0;
187 p->checking_connectivity = GRPC_CHANNEL_IDLE;
188 GRPC_LB_POLICY_WEAK_REF(&p->base, "pick_first_connectivity");
189 grpc_subchannel_notify_on_state_change(
190 exec_ctx, p->subchannels[p->checking_subchannel],
191 p->base.interested_parties, &p->checking_connectivity,
192 &p->connectivity_changed);
193 }
Craig Tiller48cb07c2015-07-15 16:16:15 -0700194}
195
Craig Tiller2400bf52017-02-09 16:25:19 -0800196static void pf_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
Craig Tillera82950e2015-09-22 12:33:20 -0700197 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillera82950e2015-09-22 12:33:20 -0700198 if (!p->started_picking) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700199 start_picking_locked(exec_ctx, p);
Craig Tillera82950e2015-09-22 12:33:20 -0700200 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700201}
202
Craig Tiller2400bf52017-02-09 16:25:19 -0800203static int pf_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
204 const grpc_lb_policy_pick_args *pick_args,
Mark D. Roth09e458c2017-05-02 08:13:26 -0700205 grpc_connected_subchannel **target,
206 grpc_call_context_element *context, void **user_data,
Craig Tiller2400bf52017-02-09 16:25:19 -0800207 grpc_closure *on_complete) {
Craig Tillera82950e2015-09-22 12:33:20 -0700208 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller45724b32015-09-22 10:42:19 -0700209 pending_pick *pp;
Craig Tiller320bee02016-01-06 17:33:45 -0800210
211 /* Check atomically for a selected channel */
Craig Tiller2400bf52017-02-09 16:25:19 -0800212 if (p->selected != NULL) {
213 *target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
Craig Tiller86c0f8a2015-12-01 20:05:40 -0800214 return 1;
215 }
Craig Tiller320bee02016-01-06 17:33:45 -0800216
Craig Tiller46dd7902017-02-23 09:42:16 -0800217 /* No subchannel selected yet, so try again */
Craig Tiller2400bf52017-02-09 16:25:19 -0800218 if (!p->started_picking) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700219 start_picking_locked(exec_ctx, p);
Craig Tillera82950e2015-09-22 12:33:20 -0700220 }
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700221 pp = (pending_pick *)gpr_malloc(sizeof(*pp));
Craig Tiller2400bf52017-02-09 16:25:19 -0800222 pp->next = p->pending_picks;
223 pp->target = target;
224 pp->initial_metadata_flags = pick_args->initial_metadata_flags;
225 pp->on_complete = on_complete;
226 p->pending_picks = pp;
227 return 0;
Craig Tiller45724b32015-09-22 10:42:19 -0700228}
229
Craig Tiller2400bf52017-02-09 16:25:19 -0800230static void destroy_subchannels_locked(grpc_exec_ctx *exec_ctx,
231 pick_first_lb_policy *p) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700232 size_t num_subchannels = p->num_subchannels;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700233 grpc_subchannel **subchannels = p->subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700234
Craig Tillerb09d84d2015-10-06 09:12:16 -0700235 p->num_subchannels = 0;
236 p->subchannels = NULL;
Craig Tiller48613042015-11-29 14:45:11 -0800237 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "destroy_subchannels");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700238
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700239 for (size_t i = 0; i < num_subchannels; i++) {
Craig Tillerb09d84d2015-10-06 09:12:16 -0700240 GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
241 }
Craig Tillerb09d84d2015-10-06 09:12:16 -0700242 gpr_free(subchannels);
243}
244
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700245static grpc_connectivity_state pf_check_connectivity_locked(
246 grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_error **error) {
247 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
248 return grpc_connectivity_state_get(&p->state_tracker, error);
249}
250
251static void pf_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx,
252 grpc_lb_policy *pol,
253 grpc_connectivity_state *current,
254 grpc_closure *notify) {
255 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
256 grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
257 current, notify);
258}
259
260static void pf_ping_one_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
261 grpc_closure *closure) {
262 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
263 if (p->selected) {
264 grpc_connected_subchannel_ping(exec_ctx, p->selected, closure);
265 } else {
ncteisen274bbbe2017-06-08 14:57:11 -0700266 GRPC_CLOSURE_SCHED(exec_ctx, closure,
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700267 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
268 }
269}
270
271/* unsubscribe all subchannels */
272static void stop_connectivity_watchers(grpc_exec_ctx *exec_ctx,
273 pick_first_lb_policy *p) {
274 if (p->num_subchannels > 0) {
275 GPR_ASSERT(p->selected == NULL);
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700276 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
277 gpr_log(GPR_DEBUG, "Pick First %p unsubscribing from subchannel %p",
278 (void *)p, (void *)p->subchannels[p->checking_subchannel]);
279 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700280 grpc_subchannel_notify_on_state_change(
281 exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
282 &p->connectivity_changed);
283 p->updating_subchannels = true;
284 } else if (p->selected != NULL) {
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700285 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
286 gpr_log(GPR_DEBUG,
287 "Pick First %p unsubscribing from selected subchannel %p",
288 (void *)p, (void *)p->selected);
289 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700290 grpc_connected_subchannel_notify_on_state_change(
291 exec_ctx, p->selected, NULL, NULL, &p->connectivity_changed);
292 p->updating_selected = true;
293 }
294}
295
296/* true upon success */
297static void pf_update_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
298 const grpc_lb_policy_args *args) {
299 pick_first_lb_policy *p = (pick_first_lb_policy *)policy;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700300 const grpc_arg *arg =
301 grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
302 if (arg == NULL || arg->type != GRPC_ARG_POINTER) {
303 if (p->subchannels == NULL) {
304 // If we don't have a current subchannel list, go into TRANSIENT FAILURE.
305 grpc_connectivity_state_set(
306 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
307 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing update in args"),
308 "pf_update_missing");
309 } else {
310 // otherwise, keep using the current subchannel list (ignore this update).
311 gpr_log(GPR_ERROR,
312 "No valid LB addresses channel arg for Pick First %p update, "
313 "ignoring.",
314 (void *)p);
315 }
316 return;
317 }
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700318 const grpc_lb_addresses *addresses =
319 (const grpc_lb_addresses *)arg->value.pointer.p;
Juanli Shen8af54b82017-08-30 15:55:10 -0700320 if (addresses->num_addresses == 0) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700321 // Empty update. Unsubscribe from all current subchannels and put the
322 // channel in TRANSIENT_FAILURE.
323 grpc_connectivity_state_set(
324 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
325 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
326 "pf_update_empty");
327 stop_connectivity_watchers(exec_ctx, p);
328 return;
329 }
330 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
331 gpr_log(GPR_INFO, "Pick First %p received update with %lu addresses",
Juanli Shen8af54b82017-08-30 15:55:10 -0700332 (void *)p, (unsigned long)addresses->num_addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700333 }
Yash Tibrewalbc130da2017-09-12 22:44:08 -0700334 grpc_subchannel_args *sc_args = (grpc_subchannel_args *)gpr_zalloc(
335 sizeof(*sc_args) * addresses->num_addresses);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700336 /* We remove the following keys in order for subchannel keys belonging to
337 * subchannels point to the same address to match. */
338 static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
339 GRPC_ARG_LB_ADDRESSES};
340 size_t sc_args_count = 0;
341
342 /* Create list of subchannel args for new addresses in \a args. */
343 for (size_t i = 0; i < addresses->num_addresses; i++) {
Juanli Shen8af54b82017-08-30 15:55:10 -0700344 // If there were any balancer, we would have chosen grpclb policy instead.
345 GPR_ASSERT(!addresses->addresses[i].is_balancer);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700346 if (addresses->addresses[i].user_data != NULL) {
347 gpr_log(GPR_ERROR,
348 "This LB policy doesn't support user data. It will be ignored");
349 }
350 grpc_arg addr_arg =
351 grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
352 grpc_channel_args *new_args = grpc_channel_args_copy_and_add_and_remove(
353 args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg,
354 1);
355 gpr_free(addr_arg.value.string);
356 sc_args[sc_args_count++].args = new_args;
357 }
358
359 /* Check if p->selected is amongst them. If so, we are done. */
360 if (p->selected != NULL) {
361 GPR_ASSERT(p->selected_key != NULL);
362 for (size_t i = 0; i < sc_args_count; i++) {
363 grpc_subchannel_key *ith_sc_key = grpc_subchannel_key_create(&sc_args[i]);
364 const bool found_selected =
365 grpc_subchannel_key_compare(p->selected_key, ith_sc_key) == 0;
366 grpc_subchannel_key_destroy(exec_ctx, ith_sc_key);
367 if (found_selected) {
368 // The currently selected subchannel is in the update: we are done.
369 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
370 gpr_log(GPR_INFO,
371 "Pick First %p found already selected subchannel %p amongst "
372 "updates. Update done.",
373 (void *)p, (void *)p->selected);
374 }
375 for (size_t j = 0; j < sc_args_count; j++) {
376 grpc_channel_args_destroy(exec_ctx,
377 (grpc_channel_args *)sc_args[j].args);
378 }
379 gpr_free(sc_args);
380 return;
381 }
382 }
383 }
384 // We only check for already running updates here because if the previous
385 // steps were successful, the update can be considered done without any
386 // interference (ie, no callbacks were scheduled).
387 if (p->updating_selected || p->updating_subchannels) {
388 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
389 gpr_log(GPR_INFO,
390 "Update already in progress for pick first %p. Deferring update.",
391 (void *)p);
392 }
393 if (p->pending_update_args != NULL) {
394 grpc_channel_args_destroy(exec_ctx, p->pending_update_args->args);
395 gpr_free(p->pending_update_args);
396 }
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700397 p->pending_update_args =
398 (grpc_lb_policy_args *)gpr_zalloc(sizeof(*p->pending_update_args));
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700399 p->pending_update_args->client_channel_factory =
400 args->client_channel_factory;
401 p->pending_update_args->args = grpc_channel_args_copy(args->args);
402 p->pending_update_args->combiner = args->combiner;
403 return;
404 }
405 /* Create the subchannels for the new subchannel args/addresses. */
406 grpc_subchannel **new_subchannels =
Yash Tibrewalbc130da2017-09-12 22:44:08 -0700407 (grpc_subchannel **)gpr_zalloc(sizeof(*new_subchannels) * sc_args_count);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700408 size_t num_new_subchannels = 0;
409 for (size_t i = 0; i < sc_args_count; i++) {
410 grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
411 exec_ctx, args->client_channel_factory, &sc_args[i]);
412 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
413 char *address_uri =
414 grpc_sockaddr_to_uri(&addresses->addresses[i].address);
415 gpr_log(GPR_INFO,
416 "Pick First %p created subchannel %p for address uri %s",
417 (void *)p, (void *)subchannel, address_uri);
418 gpr_free(address_uri);
419 }
420 grpc_channel_args_destroy(exec_ctx, (grpc_channel_args *)sc_args[i].args);
421 if (subchannel != NULL) new_subchannels[num_new_subchannels++] = subchannel;
422 }
423 gpr_free(sc_args);
424 if (num_new_subchannels == 0) {
425 gpr_free(new_subchannels);
426 // Empty update. Unsubscribe from all current subchannels and put the
427 // channel in TRANSIENT_FAILURE.
428 grpc_connectivity_state_set(
429 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
430 GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid addresses in update"),
431 "pf_update_no_valid_addresses");
432 stop_connectivity_watchers(exec_ctx, p);
433 return;
434 }
435
436 /* Destroy the current subchannels. Repurpose pf_shutdown/destroy. */
437 stop_connectivity_watchers(exec_ctx, p);
438
439 /* Save new subchannels. The switch over will happen in
440 * pf_connectivity_changed_locked */
441 if (p->updating_selected || p->updating_subchannels) {
442 p->num_new_subchannels = num_new_subchannels;
443 p->new_subchannels = new_subchannels;
444 } else { /* nothing is updating. Get things moving from here */
445 p->num_subchannels = num_new_subchannels;
446 p->subchannels = new_subchannels;
447 p->new_subchannels = NULL;
448 p->num_new_subchannels = 0;
449 if (p->started_picking) {
450 p->checking_subchannel = 0;
451 p->checking_connectivity = GRPC_CHANNEL_IDLE;
452 grpc_subchannel_notify_on_state_change(
453 exec_ctx, p->subchannels[p->checking_subchannel],
454 p->base.interested_parties, &p->checking_connectivity,
455 &p->connectivity_changed);
456 }
457 }
458}
459
Craig Tiller2400bf52017-02-09 16:25:19 -0800460static void pf_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg,
461 grpc_error *error) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700462 pick_first_lb_policy *p = (pick_first_lb_policy *)arg;
Craig Tillerb5585d42015-11-17 07:18:31 -0800463 grpc_subchannel *selected_subchannel;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700464 pending_pick *pp;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700465
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700466 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
467 gpr_log(
468 GPR_DEBUG,
469 "Pick First %p connectivity changed. Updating selected: %d; Updating "
470 "subchannels: %d; Checking %lu index (%lu total); State: %d; ",
471 (void *)p, p->updating_selected, p->updating_subchannels,
472 (unsigned long)p->checking_subchannel,
473 (unsigned long)p->num_subchannels, p->checking_connectivity);
474 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700475 bool restart = false;
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700476 if (p->updating_selected && error != GRPC_ERROR_NONE) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700477 /* Captured the unsubscription for p->selected */
478 GPR_ASSERT(p->selected != NULL);
479 GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, p->selected,
480 "pf_update_connectivity");
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700481 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
482 gpr_log(GPR_DEBUG, "Pick First %p unreffing selected subchannel %p",
483 (void *)p, (void *)p->selected);
484 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700485 p->updating_selected = false;
486 if (p->num_new_subchannels == 0) {
487 p->selected = NULL;
488 return;
489 }
490 restart = true;
491 }
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700492 if (p->updating_subchannels && error != GRPC_ERROR_NONE) {
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700493 /* Captured the unsubscription for the checking subchannel */
494 GPR_ASSERT(p->selected == NULL);
495 for (size_t i = 0; i < p->num_subchannels; i++) {
496 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i],
497 "pf_update_connectivity");
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700498 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
499 gpr_log(GPR_DEBUG, "Pick First %p unreffing subchannel %p", (void *)p,
500 (void *)p->subchannels[i]);
501 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700502 }
503 gpr_free(p->subchannels);
504 p->subchannels = NULL;
505 p->num_subchannels = 0;
506 p->updating_subchannels = false;
507 if (p->num_new_subchannels == 0) return;
508 restart = true;
509 }
510 if (restart) {
511 p->selected = NULL;
512 p->selected_key = NULL;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700513 GPR_ASSERT(p->new_subchannels != NULL);
514 GPR_ASSERT(p->num_new_subchannels > 0);
515 p->num_subchannels = p->num_new_subchannels;
516 p->subchannels = p->new_subchannels;
517 p->num_new_subchannels = 0;
518 p->new_subchannels = NULL;
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700519 if (p->started_picking) {
520 /* If we were picking, continue to do so over the new subchannels,
521 * starting from the 0th index. */
522 p->checking_subchannel = 0;
523 p->checking_connectivity = GRPC_CHANNEL_IDLE;
524 /* reuses the weak ref from start_picking_locked */
525 grpc_subchannel_notify_on_state_change(
526 exec_ctx, p->subchannels[p->checking_subchannel],
527 p->base.interested_parties, &p->checking_connectivity,
528 &p->connectivity_changed);
529 }
530 if (p->pending_update_args != NULL) {
531 const grpc_lb_policy_args *args = p->pending_update_args;
532 p->pending_update_args = NULL;
533 pf_update_locked(exec_ctx, &p->base, args);
534 }
535 return;
536 }
537 GRPC_ERROR_REF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700538 if (p->shutdown) {
Craig Tiller48613042015-11-29 14:45:11 -0800539 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tillerae125932016-05-13 16:34:29 -0700540 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700541 return;
Craig Tiller2400bf52017-02-09 16:25:19 -0800542 } else if (p->selected != NULL) {
Craig Tillercb2609f2015-11-24 17:19:19 -0800543 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
544 /* if the selected channel goes bad, we're done */
Craig Tiller48ed92e2016-06-02 11:07:12 -0700545 p->checking_connectivity = GRPC_CHANNEL_SHUTDOWN;
Craig Tillercb2609f2015-11-24 17:19:19 -0800546 }
Craig Tillera82950e2015-09-22 12:33:20 -0700547 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
Craig Tillerf707d622016-05-06 14:26:12 -0700548 p->checking_connectivity, GRPC_ERROR_REF(error),
Craig Tiller804ff712016-05-05 16:25:40 -0700549 "selected_changed");
Craig Tiller48ed92e2016-06-02 11:07:12 -0700550 if (p->checking_connectivity != GRPC_CHANNEL_SHUTDOWN) {
Craig Tillerab33b482015-11-21 08:11:04 -0800551 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller2400bf52017-02-09 16:25:19 -0800552 exec_ctx, p->selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800553 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700554 } else {
Craig Tiller48613042015-11-29 14:45:11 -0800555 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700556 }
Craig Tillera82950e2015-09-22 12:33:20 -0700557 } else {
558 loop:
559 switch (p->checking_connectivity) {
David Garcia Quintasea6689d2016-11-08 09:46:41 -0800560 case GRPC_CHANNEL_INIT:
Jan Tattermuschb0fb2d22016-11-16 14:04:05 +0100561 GPR_UNREACHABLE_CODE(return );
Craig Tillera82950e2015-09-22 12:33:20 -0700562 case GRPC_CHANNEL_READY:
563 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
Craig Tiller804ff712016-05-05 16:25:40 -0700564 GRPC_CHANNEL_READY, GRPC_ERROR_NONE,
565 "connecting_ready");
Craig Tillerb5585d42015-11-17 07:18:31 -0800566 selected_subchannel = p->subchannels[p->checking_subchannel];
Craig Tiller2400bf52017-02-09 16:25:19 -0800567 p->selected = GRPC_CONNECTED_SUBCHANNEL_REF(
568 grpc_subchannel_get_connected_subchannel(selected_subchannel),
569 "picked_first");
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700570
571 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700572 gpr_log(GPR_INFO,
573 "Pick First %p selected subchannel %p (connected %p)",
574 (void *)p, (void *)selected_subchannel, (void *)p->selected);
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700575 }
576 p->selected_key = grpc_subchannel_get_key(selected_subchannel);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700577 /* drop the pick list: we are connected now */
Craig Tiller48613042015-11-29 14:45:11 -0800578 GRPC_LB_POLICY_WEAK_REF(&p->base, "destroy_subchannels");
Craig Tiller2400bf52017-02-09 16:25:19 -0800579 destroy_subchannels_locked(exec_ctx, p);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700580 /* update any calls that were waiting for a pick */
Craig Tillera82950e2015-09-22 12:33:20 -0700581 while ((pp = p->pending_picks)) {
582 p->pending_picks = pp->next;
Craig Tiller2400bf52017-02-09 16:25:19 -0800583 *pp->target = GRPC_CONNECTED_SUBCHANNEL_REF(p->selected, "picked");
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700584 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
585 gpr_log(GPR_INFO,
586 "Servicing pending pick with selected subchannel %p",
587 (void *)p->selected);
588 }
ncteisen274bbbe2017-06-08 14:57:11 -0700589 GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700590 gpr_free(pp);
591 }
Craig Tillerab33b482015-11-21 08:11:04 -0800592 grpc_connected_subchannel_notify_on_state_change(
Craig Tiller2400bf52017-02-09 16:25:19 -0800593 exec_ctx, p->selected, p->base.interested_parties,
Craig Tillera6bebf42015-12-01 17:02:35 -0800594 &p->checking_connectivity, &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700595 break;
596 case GRPC_CHANNEL_TRANSIENT_FAILURE:
Craig Tillera82950e2015-09-22 12:33:20 -0700597 p->checking_subchannel =
598 (p->checking_subchannel + 1) % p->num_subchannels;
Craig Tiller131b6de2016-03-31 17:05:28 -0700599 if (p->checking_subchannel == 0) {
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700600 /* only trigger transient failure when we've tried all alternatives
601 */
Craig Tiller804ff712016-05-05 16:25:40 -0700602 grpc_connectivity_state_set(
603 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tillerf707d622016-05-06 14:26:12 -0700604 GRPC_ERROR_REF(error), "connecting_transient_failure");
Craig Tiller131b6de2016-03-31 17:05:28 -0700605 }
Craig Tillerf707d622016-05-06 14:26:12 -0700606 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700607 p->checking_connectivity = grpc_subchannel_check_connectivity(
Craig Tiller804ff712016-05-05 16:25:40 -0700608 p->subchannels[p->checking_subchannel], &error);
Craig Tillera82950e2015-09-22 12:33:20 -0700609 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
610 grpc_subchannel_notify_on_state_change(
611 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800612 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800613 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700614 } else {
615 goto loop;
616 }
617 break;
618 case GRPC_CHANNEL_CONNECTING:
619 case GRPC_CHANNEL_IDLE:
Craig Tiller804ff712016-05-05 16:25:40 -0700620 grpc_connectivity_state_set(
621 exec_ctx, &p->state_tracker, GRPC_CHANNEL_CONNECTING,
Craig Tillerf707d622016-05-06 14:26:12 -0700622 GRPC_ERROR_REF(error), "connecting_changed");
Craig Tillera82950e2015-09-22 12:33:20 -0700623 grpc_subchannel_notify_on_state_change(
624 exec_ctx, p->subchannels[p->checking_subchannel],
Craig Tiller69b093b2016-02-25 19:04:07 -0800625 p->base.interested_parties, &p->checking_connectivity,
Craig Tiller1d881fb2015-12-01 07:39:04 -0800626 &p->connectivity_changed);
Craig Tillera82950e2015-09-22 12:33:20 -0700627 break;
Craig Tiller48ed92e2016-06-02 11:07:12 -0700628 case GRPC_CHANNEL_SHUTDOWN:
Craig Tillera82950e2015-09-22 12:33:20 -0700629 p->num_subchannels--;
Craig Tiller86c99582015-11-25 15:22:26 -0800630 GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
631 p->subchannels[p->num_subchannels]);
Craig Tillera82950e2015-09-22 12:33:20 -0700632 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
633 "pick_first");
634 if (p->num_subchannels == 0) {
Craig Tiller804ff712016-05-05 16:25:40 -0700635 grpc_connectivity_state_set(
Craig Tillerd925c932016-06-06 08:38:50 -0700636 exec_ctx, &p->state_tracker, GRPC_CHANNEL_SHUTDOWN,
ncteisen4b36a3d2017-03-13 19:08:06 -0700637 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
638 "Pick first exhausted channels", &error, 1),
Craig Tiller804ff712016-05-05 16:25:40 -0700639 "no_more_channels");
Craig Tillera82950e2015-09-22 12:33:20 -0700640 while ((pp = p->pending_picks)) {
641 p->pending_picks = pp->next;
642 *pp->target = NULL;
ncteisen274bbbe2017-06-08 14:57:11 -0700643 GRPC_CLOSURE_SCHED(exec_ctx, pp->on_complete, GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700644 gpr_free(pp);
645 }
Craig Tiller1d881fb2015-12-01 07:39:04 -0800646 GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &p->base,
647 "pick_first_connectivity");
Craig Tillera82950e2015-09-22 12:33:20 -0700648 } else {
Craig Tiller804ff712016-05-05 16:25:40 -0700649 grpc_connectivity_state_set(
650 exec_ctx, &p->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tillerf707d622016-05-06 14:26:12 -0700651 GRPC_ERROR_REF(error), "subchannel_failed");
Craig Tillera82950e2015-09-22 12:33:20 -0700652 p->checking_subchannel %= p->num_subchannels;
Craig Tillerf707d622016-05-06 14:26:12 -0700653 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700654 p->checking_connectivity = grpc_subchannel_check_connectivity(
Craig Tiller804ff712016-05-05 16:25:40 -0700655 p->subchannels[p->checking_subchannel], &error);
Craig Tillera82950e2015-09-22 12:33:20 -0700656 goto loop;
657 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700658 }
Craig Tillera82950e2015-09-22 12:33:20 -0700659 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700660
Craig Tillerf707d622016-05-06 14:26:12 -0700661 GRPC_ERROR_UNREF(error);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700662}
663
664static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
Craig Tiller2400bf52017-02-09 16:25:19 -0800665 pf_destroy,
666 pf_shutdown_locked,
667 pf_pick_locked,
668 pf_cancel_pick_locked,
669 pf_cancel_picks_locked,
670 pf_ping_one_locked,
671 pf_exit_idle_locked,
672 pf_check_connectivity_locked,
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700673 pf_notify_on_state_change_locked,
674 pf_update_locked};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700675
Craig Tillera82950e2015-09-22 12:33:20 -0700676static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700677
Craig Tillera82950e2015-09-22 12:33:20 -0700678static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700679
David Garcia Quintas67c0d042016-03-25 01:37:53 -0700680static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
681 grpc_lb_policy_factory *factory,
Craig Tillera82950e2015-09-22 12:33:20 -0700682 grpc_lb_policy_args *args) {
David Garcia Quintas86fcfcc2016-03-31 23:22:28 -0700683 GPR_ASSERT(args->client_channel_factory != NULL);
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700684 pick_first_lb_policy *p = (pick_first_lb_policy *)gpr_zalloc(sizeof(*p));
David Garcia Quintasaf084dc2017-06-27 13:42:54 -0700685 if (GRPC_TRACER_ON(grpc_lb_pick_first_trace)) {
686 gpr_log(GPR_DEBUG, "Pick First %p created.", (void *)p);
687 }
David Garcia Quintas87d5a312017-06-06 19:45:58 -0700688 pf_update_locked(exec_ctx, &p->base, args);
Craig Tiller2400bf52017-02-09 16:25:19 -0800689 grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable, args->combiner);
Juanli Shen6502ecc2017-09-13 13:10:54 -0700690 grpc_subchannel_index_ref();
ncteisen274bbbe2017-06-08 14:57:11 -0700691 GRPC_CLOSURE_INIT(&p->connectivity_changed, pf_connectivity_changed_locked, p,
Craig Tilleree4b1452017-05-12 10:56:03 -0700692 grpc_combiner_scheduler(args->combiner));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700693 return &p->base;
694}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700695
696static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700697 pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
698 "pick_first"};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700699
700static grpc_lb_policy_factory pick_first_lb_policy_factory = {
Craig Tillera82950e2015-09-22 12:33:20 -0700701 &pick_first_factory_vtable};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700702
Craig Tillerfb433852016-03-29 08:51:07 -0700703static grpc_lb_policy_factory *pick_first_lb_factory_create() {
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700704 return &pick_first_lb_policy_factory;
705}
Craig Tillerfb433852016-03-29 08:51:07 -0700706
707/* Plugin registration */
708
Yash Tibrewal83062842017-09-21 18:56:08 -0700709extern "C" void grpc_lb_policy_pick_first_init() {
Craig Tiller3113ef42016-03-29 09:03:14 -0700710 grpc_register_lb_policy(pick_first_lb_factory_create());
ncteisen06bce6e2017-07-10 07:58:49 -0700711 grpc_register_tracer(&grpc_lb_pick_first_trace);
Craig Tillerfb433852016-03-29 08:51:07 -0700712}
713
Yash Tibrewal83062842017-09-21 18:56:08 -0700714extern "C" void grpc_lb_policy_pick_first_shutdown() {}