blob: 93312abb00eb3974e9d0e6c48569381e4e3d7998 [file] [log] [blame]
Craig Tiller3bc8ebd2015-06-24 15:41:15 -07001/*
2 *
3 * Copyright 2015, Google Inc.
4 * 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
David Garcia Quintas5c4543d2015-09-03 15:49:56 -070034#include "src/core/client_config/lb_policy_factory.h"
Craig Tiller3bc8ebd2015-06-24 15:41:15 -070035#include "src/core/client_config/lb_policies/pick_first.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;
45 grpc_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
58 /** mutex protecting remaining members */
59 gpr_mu mu;
60 /** the selected channel
61 TODO(ctiller): this should be atomically set so we don't
62 need to take a mutex in the common case */
63 grpc_subchannel *selected;
64 /** have we started picking? */
65 int started_picking;
Craig Tillera14215a2015-07-17 17:21:08 -070066 /** are we shut down? */
67 int shutdown;
Craig Tillereb3b12e2015-06-26 14:42:49 -070068 /** which subchannel are we watching? */
69 size_t checking_subchannel;
70 /** what is the connectivity of that channel? */
71 grpc_connectivity_state checking_connectivity;
72 /** list of picks that are waiting on connectivity */
73 pending_pick *pending_picks;
Craig Tillerc7b5f762015-06-27 11:48:42 -070074
75 /** our connectivity state tracker */
76 grpc_connectivity_state_tracker state_tracker;
Craig Tillereb3b12e2015-06-26 14:42:49 -070077} pick_first_lb_policy;
78
Craig Tillera82950e2015-09-22 12:33:20 -070079static void del_interested_parties_locked(grpc_exec_ctx *exec_ctx,
80 pick_first_lb_policy *p) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -070081 pending_pick *pp;
Craig Tillera82950e2015-09-22 12:33:20 -070082 for (pp = p->pending_picks; pp; pp = pp->next) {
83 grpc_subchannel_del_interested_party(
84 exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
85 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -070086}
87
Craig Tillera82950e2015-09-22 12:33:20 -070088static void add_interested_parties_locked(grpc_exec_ctx *exec_ctx,
89 pick_first_lb_policy *p) {
Craig Tiller1ada6ad2015-07-16 16:19:14 -070090 pending_pick *pp;
Craig Tillera82950e2015-09-22 12:33:20 -070091 for (pp = p->pending_picks; pp; pp = pp->next) {
92 grpc_subchannel_add_interested_party(
93 exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
94 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -070095}
96
Craig Tillera82950e2015-09-22 12:33:20 -070097void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
98 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerd7b68e72015-06-28 11:41:09 -070099 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -0700100 GPR_ASSERT(p->pending_picks == NULL);
101 for (i = 0; i < p->num_subchannels; i++) {
102 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
103 }
Craig Tiller89a768e2015-10-06 09:55:59 -0700104 if (p->selected) {
105 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->selected, "picked_first");
106 }
Craig Tillera82950e2015-09-22 12:33:20 -0700107 grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
108 gpr_free(p->subchannels);
109 gpr_mu_destroy(&p->mu);
110 gpr_free(p);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700111}
112
Craig Tillera82950e2015-09-22 12:33:20 -0700113void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
114 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerd2cc4592015-07-01 07:50:47 -0700115 pending_pick *pp;
Craig Tillera82950e2015-09-22 12:33:20 -0700116 gpr_mu_lock(&p->mu);
117 del_interested_parties_locked(exec_ctx, p);
Craig Tillera14215a2015-07-17 17:21:08 -0700118 p->shutdown = 1;
Craig Tiller5795da72015-09-17 15:27:13 -0700119 pp = p->pending_picks;
120 p->pending_picks = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700121 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
122 GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
123 gpr_mu_unlock(&p->mu);
124 while (pp != NULL) {
125 pending_pick *next = pp->next;
126 *pp->target = NULL;
127 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
128 gpr_free(pp);
129 pp = next;
130 }
Craig Tillereb3b12e2015-06-26 14:42:49 -0700131}
132
Craig Tiller577c9b22015-11-02 14:11:15 -0800133static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
134 grpc_subchannel **target) {
135 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
136 pending_pick *pp;
137 gpr_mu_lock(&p->mu);
138 pp = p->pending_picks;
139 p->pending_picks = NULL;
140 while (pp != NULL) {
141 pending_pick *next = pp->next;
142 if (pp->target == target) {
143 grpc_subchannel_del_interested_party(
144 exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
145 *target = NULL;
146 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 0);
147 gpr_free(pp);
148 } else {
149 pp->next = p->pending_picks;
150 p->pending_picks = pp;
151 }
152 pp = next;
153 }
154 gpr_mu_unlock(&p->mu);
155}
156
Craig Tillera82950e2015-09-22 12:33:20 -0700157static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
Craig Tiller48cb07c2015-07-15 16:16:15 -0700158 p->started_picking = 1;
159 p->checking_subchannel = 0;
160 p->checking_connectivity = GRPC_CHANNEL_IDLE;
Craig Tillera82950e2015-09-22 12:33:20 -0700161 GRPC_LB_POLICY_REF(&p->base, "pick_first_connectivity");
162 grpc_subchannel_notify_on_state_change(
163 exec_ctx, p->subchannels[p->checking_subchannel],
164 &p->checking_connectivity, &p->connectivity_changed);
Craig Tiller48cb07c2015-07-15 16:16:15 -0700165}
166
Craig Tillera82950e2015-09-22 12:33:20 -0700167void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
168 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
169 gpr_mu_lock(&p->mu);
170 if (!p->started_picking) {
171 start_picking(exec_ctx, p);
172 }
173 gpr_mu_unlock(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700174}
175
Craig Tiller577c9b22015-11-02 14:11:15 -0800176int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_pollset *pollset,
177 grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
178 grpc_closure *on_complete) {
Craig Tillera82950e2015-09-22 12:33:20 -0700179 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tiller45724b32015-09-22 10:42:19 -0700180 pending_pick *pp;
Craig Tillera82950e2015-09-22 12:33:20 -0700181 gpr_mu_lock(&p->mu);
182 if (p->selected) {
183 gpr_mu_unlock(&p->mu);
184 *target = p->selected;
Craig Tiller577c9b22015-11-02 14:11:15 -0800185 return 1;
Craig Tillera82950e2015-09-22 12:33:20 -0700186 } else {
187 if (!p->started_picking) {
188 start_picking(exec_ctx, p);
Craig Tiller45724b32015-09-22 10:42:19 -0700189 }
Craig Tillera82950e2015-09-22 12:33:20 -0700190 grpc_subchannel_add_interested_party(
191 exec_ctx, p->subchannels[p->checking_subchannel], pollset);
192 pp = gpr_malloc(sizeof(*pp));
193 pp->next = p->pending_picks;
194 pp->pollset = pollset;
195 pp->target = target;
196 pp->on_complete = on_complete;
197 p->pending_picks = pp;
198 gpr_mu_unlock(&p->mu);
Craig Tiller577c9b22015-11-02 14:11:15 -0800199 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700200 }
Craig Tiller45724b32015-09-22 10:42:19 -0700201}
202
Craig Tiller1f41b6b2015-10-09 15:07:02 -0700203static void destroy_subchannels(grpc_exec_ctx *exec_ctx, void *arg,
Craig Tillerb09d84d2015-10-06 09:12:16 -0700204 int iomgr_success) {
205 pick_first_lb_policy *p = arg;
206 size_t i;
207 grpc_transport_op op;
208 size_t num_subchannels = p->num_subchannels;
209 grpc_subchannel **subchannels;
210 grpc_subchannel *exclude_subchannel;
211
212 gpr_mu_lock(&p->mu);
213 subchannels = p->subchannels;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700214 p->num_subchannels = 0;
215 p->subchannels = NULL;
Craig Tiller89a768e2015-10-06 09:55:59 -0700216 exclude_subchannel = p->selected;
Craig Tillerb09d84d2015-10-06 09:12:16 -0700217 gpr_mu_unlock(&p->mu);
218 GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "destroy_subchannels");
219
220 for (i = 0; i < num_subchannels; i++) {
Craig Tiller89a768e2015-10-06 09:55:59 -0700221 if (subchannels[i] != exclude_subchannel) {
222 memset(&op, 0, sizeof(op));
223 op.disconnect = 1;
224 grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], &op);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700225 }
Craig Tillerb09d84d2015-10-06 09:12:16 -0700226 GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pick_first");
227 }
228
229 gpr_free(subchannels);
230}
231
Craig Tillera82950e2015-09-22 12:33:20 -0700232static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
233 int iomgr_success) {
Craig Tillereb3b12e2015-06-26 14:42:49 -0700234 pick_first_lb_policy *p = arg;
235 pending_pick *pp;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700236
Craig Tillera82950e2015-09-22 12:33:20 -0700237 gpr_mu_lock(&p->mu);
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700238
Craig Tillera82950e2015-09-22 12:33:20 -0700239 if (p->shutdown) {
240 gpr_mu_unlock(&p->mu);
241 GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
242 return;
243 } else if (p->selected != NULL) {
244 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
245 p->checking_connectivity, "selected_changed");
246 if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
247 grpc_subchannel_notify_on_state_change(exec_ctx, p->selected,
248 &p->checking_connectivity,
249 &p->connectivity_changed);
250 } else {
251 GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700252 }
Craig Tillera82950e2015-09-22 12:33:20 -0700253 } else {
254 loop:
255 switch (p->checking_connectivity) {
256 case GRPC_CHANNEL_READY:
257 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
258 GRPC_CHANNEL_READY, "connecting_ready");
259 p->selected = p->subchannels[p->checking_subchannel];
Craig Tiller89a768e2015-10-06 09:55:59 -0700260 GRPC_SUBCHANNEL_REF(p->selected, "picked_first");
Craig Tillerb09d84d2015-10-06 09:12:16 -0700261 /* drop the pick list: we are connected now */
262 GRPC_LB_POLICY_REF(&p->base, "destroy_subchannels");
Craig Tiller1f41b6b2015-10-09 15:07:02 -0700263 grpc_exec_ctx_enqueue(exec_ctx,
264 grpc_closure_create(destroy_subchannels, p), 1);
Craig Tillerb09d84d2015-10-06 09:12:16 -0700265 /* update any calls that were waiting for a pick */
Craig Tillera82950e2015-09-22 12:33:20 -0700266 while ((pp = p->pending_picks)) {
267 p->pending_picks = pp->next;
268 *pp->target = p->selected;
269 grpc_subchannel_del_interested_party(exec_ctx, p->selected,
270 pp->pollset);
271 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
272 gpr_free(pp);
273 }
274 grpc_subchannel_notify_on_state_change(exec_ctx, p->selected,
275 &p->checking_connectivity,
276 &p->connectivity_changed);
277 break;
278 case GRPC_CHANNEL_TRANSIENT_FAILURE:
279 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
280 GRPC_CHANNEL_TRANSIENT_FAILURE,
281 "connecting_transient_failure");
282 del_interested_parties_locked(exec_ctx, p);
283 p->checking_subchannel =
284 (p->checking_subchannel + 1) % p->num_subchannels;
285 p->checking_connectivity = grpc_subchannel_check_connectivity(
286 p->subchannels[p->checking_subchannel]);
287 add_interested_parties_locked(exec_ctx, p);
288 if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
289 grpc_subchannel_notify_on_state_change(
290 exec_ctx, p->subchannels[p->checking_subchannel],
291 &p->checking_connectivity, &p->connectivity_changed);
292 } else {
293 goto loop;
294 }
295 break;
296 case GRPC_CHANNEL_CONNECTING:
297 case GRPC_CHANNEL_IDLE:
298 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
299 GRPC_CHANNEL_CONNECTING,
300 "connecting_changed");
301 grpc_subchannel_notify_on_state_change(
302 exec_ctx, p->subchannels[p->checking_subchannel],
303 &p->checking_connectivity, &p->connectivity_changed);
304 break;
305 case GRPC_CHANNEL_FATAL_FAILURE:
306 del_interested_parties_locked(exec_ctx, p);
307 GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
308 p->subchannels[p->num_subchannels - 1]);
309 p->num_subchannels--;
310 GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
311 "pick_first");
312 if (p->num_subchannels == 0) {
313 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
314 GRPC_CHANNEL_FATAL_FAILURE,
315 "no_more_channels");
316 while ((pp = p->pending_picks)) {
317 p->pending_picks = pp->next;
318 *pp->target = NULL;
319 grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
320 gpr_free(pp);
321 }
322 GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
323 } else {
324 grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
325 GRPC_CHANNEL_TRANSIENT_FAILURE,
326 "subchannel_failed");
327 p->checking_subchannel %= p->num_subchannels;
328 p->checking_connectivity = grpc_subchannel_check_connectivity(
329 p->subchannels[p->checking_subchannel]);
330 add_interested_parties_locked(exec_ctx, p);
331 goto loop;
332 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700333 }
Craig Tillera82950e2015-09-22 12:33:20 -0700334 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -0700335
Craig Tillera82950e2015-09-22 12:33:20 -0700336 gpr_mu_unlock(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700337}
338
Craig Tillera82950e2015-09-22 12:33:20 -0700339static void pf_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
340 grpc_transport_op *op) {
341 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerc7b5f762015-06-27 11:48:42 -0700342 size_t i;
343 size_t n;
344 grpc_subchannel **subchannels;
Craig Tiller89a768e2015-10-06 09:55:59 -0700345 grpc_subchannel *selected;
Craig Tillerc7b5f762015-06-27 11:48:42 -0700346
Craig Tillera82950e2015-09-22 12:33:20 -0700347 gpr_mu_lock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700348 n = p->num_subchannels;
Craig Tillera82950e2015-09-22 12:33:20 -0700349 subchannels = gpr_malloc(n * sizeof(*subchannels));
Craig Tiller89a768e2015-10-06 09:55:59 -0700350 selected = p->selected;
351 if (selected) {
352 GRPC_SUBCHANNEL_REF(selected, "pf_broadcast_to_selected");
353 }
Craig Tillera82950e2015-09-22 12:33:20 -0700354 for (i = 0; i < n; i++) {
355 subchannels[i] = p->subchannels[i];
356 GRPC_SUBCHANNEL_REF(subchannels[i], "pf_broadcast");
357 }
358 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700359
Craig Tillera82950e2015-09-22 12:33:20 -0700360 for (i = 0; i < n; i++) {
Craig Tiller89a768e2015-10-06 09:55:59 -0700361 if (selected == subchannels[i]) continue;
Craig Tillera82950e2015-09-22 12:33:20 -0700362 grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], op);
363 GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pf_broadcast");
364 }
Craig Tiller89a768e2015-10-06 09:55:59 -0700365 if (p->selected) {
366 grpc_subchannel_process_transport_op(exec_ctx, selected, op);
367 GRPC_SUBCHANNEL_UNREF(exec_ctx, selected, "pf_broadcast_to_selected");
368 }
Craig Tillera82950e2015-09-22 12:33:20 -0700369 gpr_free(subchannels);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700370}
371
Craig Tillera82950e2015-09-22 12:33:20 -0700372static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
373 grpc_lb_policy *pol) {
374 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
Craig Tillerc7b5f762015-06-27 11:48:42 -0700375 grpc_connectivity_state st;
Craig Tillera82950e2015-09-22 12:33:20 -0700376 gpr_mu_lock(&p->mu);
377 st = grpc_connectivity_state_check(&p->state_tracker);
378 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700379 return st;
380}
381
Craig Tillera82950e2015-09-22 12:33:20 -0700382void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
383 grpc_connectivity_state *current,
384 grpc_closure *notify) {
385 pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
386 gpr_mu_lock(&p->mu);
387 grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
388 current, notify);
389 gpr_mu_unlock(&p->mu);
Craig Tillerc7b5f762015-06-27 11:48:42 -0700390}
391
Craig Tillereb3b12e2015-06-26 14:42:49 -0700392static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
Craig Tiller577c9b22015-11-02 14:11:15 -0800393 pf_destroy, pf_shutdown, pf_pick, pf_cancel_pick, pf_exit_idle,
394 pf_broadcast, pf_check_connectivity, pf_notify_on_state_change};
Craig Tillereb3b12e2015-06-26 14:42:49 -0700395
Craig Tillera82950e2015-09-22 12:33:20 -0700396static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700397
Craig Tillera82950e2015-09-22 12:33:20 -0700398static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700399
Craig Tillera82950e2015-09-22 12:33:20 -0700400static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
401 grpc_lb_policy_args *args) {
402 pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
403 GPR_ASSERT(args->num_subchannels > 0);
404 memset(p, 0, sizeof(*p));
405 grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
406 p->subchannels =
407 gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
David Garcia Quintasc7705c72015-09-09 17:21:11 -0700408 p->num_subchannels = args->num_subchannels;
Craig Tillera82950e2015-09-22 12:33:20 -0700409 grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
410 "pick_first");
411 memcpy(p->subchannels, args->subchannels,
412 sizeof(grpc_subchannel *) * args->num_subchannels);
413 grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
414 gpr_mu_init(&p->mu);
Craig Tillereb3b12e2015-06-26 14:42:49 -0700415 return &p->base;
416}
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700417
418static const grpc_lb_policy_factory_vtable pick_first_factory_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700419 pick_first_factory_ref, pick_first_factory_unref, create_pick_first,
420 "pick_first"};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700421
422static grpc_lb_policy_factory pick_first_lb_policy_factory = {
Craig Tillera82950e2015-09-22 12:33:20 -0700423 &pick_first_factory_vtable};
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700424
Craig Tillera82950e2015-09-22 12:33:20 -0700425grpc_lb_policy_factory *grpc_pick_first_lb_factory_create() {
David Garcia Quintas5c4543d2015-09-03 15:49:56 -0700426 return &pick_first_lb_policy_factory;
427}