grpc 0.13.0 → 0.13.1.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/Makefile +1114 -937
  4. data/include/grpc/census.h +71 -89
  5. data/include/grpc/compression.h +7 -7
  6. data/include/grpc/grpc.h +65 -68
  7. data/include/grpc/grpc_security.h +38 -38
  8. data/include/grpc/impl/codegen/alloc.h +7 -7
  9. data/include/grpc/impl/codegen/byte_buffer.h +13 -13
  10. data/include/grpc/impl/codegen/grpc_types.h +7 -2
  11. data/include/grpc/impl/codegen/log.h +5 -5
  12. data/include/grpc/impl/codegen/port_platform.h +14 -6
  13. data/include/grpc/impl/codegen/slice.h +15 -15
  14. data/include/grpc/impl/codegen/slice_buffer.h +17 -17
  15. data/include/grpc/impl/codegen/sync.h +26 -22
  16. data/include/grpc/impl/codegen/time.h +22 -24
  17. data/include/grpc/support/avl.h +9 -8
  18. data/include/grpc/support/cmdline.h +12 -12
  19. data/include/grpc/support/cpu.h +2 -2
  20. data/include/grpc/support/histogram.h +22 -22
  21. data/include/grpc/support/host_port.h +2 -2
  22. data/include/grpc/support/log_win32.h +1 -1
  23. data/include/grpc/support/string_util.h +2 -2
  24. data/include/grpc/support/subprocess.h +5 -5
  25. data/include/grpc/support/thd.h +9 -9
  26. data/include/grpc/support/useful.h +3 -1
  27. data/src/core/census/context.c +64 -85
  28. data/src/core/census/grpc_filter.c +2 -2
  29. data/src/core/census/mlog.c +600 -0
  30. data/src/core/census/mlog.h +95 -0
  31. data/src/core/channel/channel_args.c +67 -6
  32. data/src/core/channel/channel_args.h +7 -1
  33. data/src/core/channel/client_channel.c +26 -36
  34. data/src/core/channel/client_uchannel.c +1 -1
  35. data/src/core/channel/http_client_filter.c +2 -2
  36. data/src/core/channel/http_server_filter.c +2 -2
  37. data/src/core/channel/subchannel_call_holder.c +5 -7
  38. data/src/core/client_config/connector.c +3 -2
  39. data/src/core/client_config/connector.h +2 -2
  40. data/src/core/client_config/lb_policies/load_balancer_api.c +163 -0
  41. data/src/core/client_config/lb_policies/load_balancer_api.h +85 -0
  42. data/src/core/client_config/lb_policies/pick_first.c +10 -11
  43. data/src/core/client_config/lb_policies/round_robin.c +7 -8
  44. data/src/core/client_config/lb_policy.c +3 -3
  45. data/src/core/client_config/lb_policy.h +3 -2
  46. data/src/core/client_config/subchannel.c +51 -21
  47. data/src/core/client_config/subchannel.h +15 -6
  48. data/src/core/client_config/subchannel_index.c +261 -0
  49. data/src/core/client_config/subchannel_index.h +77 -0
  50. data/src/core/compression/{algorithm.c → compression_algorithm.c} +0 -0
  51. data/src/core/httpcli/httpcli.c +13 -11
  52. data/src/core/httpcli/httpcli.h +3 -2
  53. data/src/core/httpcli/httpcli_security_connector.c +7 -7
  54. data/src/core/iomgr/fd_posix.c +4 -2
  55. data/src/core/iomgr/iocp_windows.c +10 -6
  56. data/src/core/iomgr/iocp_windows.h +9 -2
  57. data/src/core/iomgr/iomgr.c +18 -2
  58. data/src/core/iomgr/iomgr_internal.h +5 -1
  59. data/src/core/iomgr/pollset.h +9 -10
  60. data/src/core/iomgr/pollset_multipoller_with_epoll.c +1 -0
  61. data/src/core/iomgr/pollset_multipoller_with_poll_posix.c +10 -5
  62. data/src/core/iomgr/pollset_posix.c +30 -35
  63. data/src/core/iomgr/pollset_posix.h +10 -6
  64. data/src/core/iomgr/pollset_set.h +3 -9
  65. data/src/core/iomgr/pollset_set_posix.c +23 -3
  66. data/src/core/iomgr/pollset_set_posix.h +2 -18
  67. data/src/core/iomgr/pollset_set_windows.c +3 -3
  68. data/src/core/iomgr/pollset_set_windows.h +2 -2
  69. data/src/core/iomgr/pollset_windows.c +24 -21
  70. data/src/core/iomgr/pollset_windows.h +1 -5
  71. data/src/core/iomgr/tcp_client_posix.c +7 -5
  72. data/src/core/iomgr/tcp_posix.c +4 -2
  73. data/src/core/iomgr/tcp_server_windows.c +1 -2
  74. data/src/core/iomgr/timer.c +2 -3
  75. data/src/core/iomgr/timer.h +21 -1
  76. data/src/core/iomgr/timer_heap.c +10 -12
  77. data/src/core/iomgr/udp_server.c +5 -4
  78. data/src/core/iomgr/udp_server.h +1 -0
  79. data/src/core/iomgr/workqueue_posix.c +1 -0
  80. data/src/core/iomgr/workqueue_posix.h +3 -1
  81. data/src/core/proto/grpc/lb/v0/load_balancer.pb.c +119 -0
  82. data/src/core/proto/grpc/lb/v0/load_balancer.pb.h +182 -0
  83. data/src/core/security/{base64.c → b64.c} +1 -1
  84. data/src/core/security/{base64.h → b64.h} +1 -1
  85. data/src/core/security/client_auth_filter.c +0 -1
  86. data/src/core/security/credentials.c +12 -5
  87. data/src/core/security/credentials.h +3 -3
  88. data/src/core/security/google_default_credentials.c +24 -19
  89. data/src/core/security/handshake.c +15 -7
  90. data/src/core/security/handshake.h +2 -1
  91. data/src/core/security/json_token.c +1 -1
  92. data/src/core/security/jwt_verifier.c +1 -1
  93. data/src/core/security/security_connector.c +84 -64
  94. data/src/core/security/security_connector.h +42 -22
  95. data/src/core/security/security_context.c +8 -3
  96. data/src/core/security/server_auth_filter.c +2 -2
  97. data/src/core/security/server_secure_chttp2.c +7 -7
  98. data/src/core/support/avl.c +2 -2
  99. data/src/core/support/env_linux.c +17 -0
  100. data/src/core/support/{file.c → load_file.c} +2 -2
  101. data/src/core/support/{file.h → load_file.h} +4 -12
  102. data/src/core/support/sync.c +6 -1
  103. data/src/core/support/time_posix.c +1 -1
  104. data/src/core/{iomgr/timer_internal.h → support/tmpfile.h} +17 -23
  105. data/src/core/support/{file_posix.c → tmpfile_posix.c} +2 -2
  106. data/src/core/support/{file_win32.c → tmpfile_win32.c} +2 -2
  107. data/src/core/surface/alarm.c +3 -2
  108. data/src/core/surface/call.c +102 -52
  109. data/src/core/surface/channel_create.c +1 -1
  110. data/src/core/surface/completion_queue.c +73 -41
  111. data/src/core/surface/init.c +4 -0
  112. data/src/core/surface/lame_client.c +1 -2
  113. data/src/core/surface/secure_channel_create.c +6 -7
  114. data/src/core/surface/server.c +13 -5
  115. data/src/core/surface/validate_metadata.c +1 -1
  116. data/src/core/surface/version.c +1 -1
  117. data/src/core/transport/chttp2/internal.h +22 -10
  118. data/src/core/transport/chttp2/parsing.c +3 -3
  119. data/src/core/transport/chttp2/stream_lists.c +39 -21
  120. data/src/core/transport/chttp2/writing.c +19 -28
  121. data/src/core/transport/chttp2_transport.c +80 -37
  122. data/src/core/transport/metadata.c +8 -0
  123. data/src/core/transport/static_metadata.c +17 -17
  124. data/src/core/transport/static_metadata.h +3 -3
  125. data/src/core/transport/transport.c +2 -1
  126. data/src/core/transport/transport.h +12 -5
  127. data/src/ruby/ext/grpc/extconf.rb +1 -0
  128. data/src/ruby/ext/grpc/rb_call.c +6 -0
  129. data/src/ruby/ext/grpc/rb_call_credentials.c +12 -14
  130. data/src/ruby/ext/grpc/rb_channel.c +8 -14
  131. data/src/ruby/ext/grpc/rb_channel_credentials.c +11 -12
  132. data/src/ruby/ext/grpc/rb_grpc.c +19 -18
  133. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -0
  134. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +8 -2
  135. data/src/ruby/lib/grpc/core/time_consts.rb +2 -2
  136. data/src/ruby/lib/grpc/errors.rb +2 -2
  137. data/src/ruby/lib/grpc/generic/rpc_server.rb +58 -39
  138. data/src/ruby/lib/grpc/version.rb +1 -1
  139. data/src/ruby/pb/README.md +2 -2
  140. data/src/ruby/pb/generate_proto_ruby.sh +2 -2
  141. data/src/ruby/pb/grpc/health/checker.rb +11 -11
  142. data/src/ruby/pb/grpc/health/v1/health.rb +28 -0
  143. data/src/ruby/pb/grpc/health/{v1alpha → v1}/health_services.rb +4 -4
  144. data/src/ruby/spec/client_server_spec.rb +2 -1
  145. data/src/ruby/spec/generic/rpc_server_spec.rb +3 -22
  146. data/src/ruby/spec/pb/health/checker_spec.rb +22 -36
  147. data/third_party/nanopb/pb.h +547 -0
  148. data/third_party/nanopb/pb_common.c +97 -0
  149. data/third_party/nanopb/pb_common.h +42 -0
  150. data/third_party/nanopb/pb_decode.c +1319 -0
  151. data/third_party/nanopb/pb_decode.h +149 -0
  152. data/third_party/nanopb/pb_encode.c +690 -0
  153. data/third_party/nanopb/pb_encode.h +154 -0
  154. metadata +32 -16
  155. data/src/ruby/pb/grpc/health/v1alpha/health.rb +0 -29
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  *
3
- * Copyright 2015, Google Inc.
3
+ * Copyright 2015-2016, Google Inc.
4
4
  * All rights reserved.
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
@@ -48,7 +48,8 @@ typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel,
48
48
  struct grpc_lb_policy {
49
49
  const grpc_lb_policy_vtable *vtable;
50
50
  gpr_atm ref_pair;
51
- grpc_pollset_set interested_parties;
51
+ /* owned pointer to interested parties in load balancing decisions */
52
+ grpc_pollset_set *interested_parties;
52
53
  };
53
54
 
54
55
  struct grpc_lb_policy_vtable {
@@ -36,16 +36,17 @@
36
36
  #include <string.h>
37
37
 
38
38
  #include <grpc/support/alloc.h>
39
+ #include <grpc/support/avl.h>
39
40
 
40
41
  #include "src/core/channel/channel_args.h"
41
42
  #include "src/core/channel/client_channel.h"
42
43
  #include "src/core/channel/connected_channel.h"
43
44
  #include "src/core/client_config/initial_connect_string.h"
45
+ #include "src/core/client_config/subchannel_index.h"
44
46
  #include "src/core/iomgr/timer.h"
45
47
  #include "src/core/profiling/timers.h"
46
48
  #include "src/core/surface/channel.h"
47
49
  #include "src/core/transport/connectivity_state.h"
48
- #include "src/core/transport/connectivity_state.h"
49
50
 
50
51
  #define INTERNAL_REF_BITS 16
51
52
  #define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
@@ -94,6 +95,8 @@ struct grpc_subchannel {
94
95
  struct sockaddr *addr;
95
96
  size_t addr_len;
96
97
 
98
+ grpc_subchannel_key *key;
99
+
97
100
  /** initial string to send to peer */
98
101
  gpr_slice initial_connect_string;
99
102
 
@@ -105,7 +108,7 @@ struct grpc_subchannel {
105
108
 
106
109
  /** pollset_set tracking who's interested in a connection
107
110
  being setup */
108
- grpc_pollset_set pollset_set;
111
+ grpc_pollset_set *pollset_set;
109
112
 
110
113
  /** active connection, or null; of type grpc_connected_subchannel */
111
114
  gpr_atm connected_subchannel;
@@ -206,7 +209,8 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, void *arg,
206
209
  gpr_slice_unref(c->initial_connect_string);
207
210
  grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
208
211
  grpc_connector_unref(exec_ctx, c->connector);
209
- grpc_pollset_set_destroy(&c->pollset_set);
212
+ grpc_pollset_set_destroy(c->pollset_set);
213
+ grpc_subchannel_key_destroy(exec_ctx, c->key);
210
214
  gpr_free(c);
211
215
  }
212
216
 
@@ -222,22 +226,42 @@ static gpr_atm ref_mutate(grpc_subchannel *c, gpr_atm delta,
222
226
  return old_val;
223
227
  }
224
228
 
225
- void grpc_subchannel_ref(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
229
+ grpc_subchannel *grpc_subchannel_ref(grpc_subchannel *c
230
+ GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
226
231
  gpr_atm old_refs;
227
232
  old_refs = ref_mutate(c, (1 << INTERNAL_REF_BITS),
228
233
  0 REF_MUTATE_PURPOSE("STRONG_REF"));
229
234
  GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0);
235
+ return c;
230
236
  }
231
237
 
232
- void grpc_subchannel_weak_ref(grpc_subchannel *c
233
- GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
238
+ grpc_subchannel *grpc_subchannel_weak_ref(grpc_subchannel *c
239
+ GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
234
240
  gpr_atm old_refs;
235
241
  old_refs = ref_mutate(c, 1, 0 REF_MUTATE_PURPOSE("WEAK_REF"));
236
242
  GPR_ASSERT(old_refs != 0);
243
+ return c;
244
+ }
245
+
246
+ grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
247
+ grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
248
+ if (!c) return NULL;
249
+ for (;;) {
250
+ gpr_atm old_refs = gpr_atm_acq_load(&c->ref_pair);
251
+ if (old_refs >= (1 << INTERNAL_REF_BITS)) {
252
+ gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS);
253
+ if (gpr_atm_rel_cas(&c->ref_pair, old_refs, new_refs)) {
254
+ return c;
255
+ }
256
+ } else {
257
+ return NULL;
258
+ }
259
+ }
237
260
  }
238
261
 
239
262
  static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
240
263
  grpc_connected_subchannel *con;
264
+ grpc_subchannel_index_unregister(exec_ctx, c->key, c);
241
265
  gpr_mu_lock(&c->mu);
242
266
  GPR_ASSERT(!c->disconnected);
243
267
  c->disconnected = 1;
@@ -276,10 +300,19 @@ static uint32_t random_seed() {
276
300
  return (uint32_t)(gpr_time_to_millis(gpr_now(GPR_CLOCK_MONOTONIC)));
277
301
  }
278
302
 
279
- grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
303
+ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
304
+ grpc_connector *connector,
280
305
  grpc_subchannel_args *args) {
281
- grpc_subchannel *c = gpr_malloc(sizeof(*c));
306
+ grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
307
+ grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
308
+ if (c) {
309
+ grpc_subchannel_key_destroy(exec_ctx, key);
310
+ return c;
311
+ }
312
+
313
+ c = gpr_malloc(sizeof(*c));
282
314
  memset(c, 0, sizeof(*c));
315
+ c->key = key;
283
316
  gpr_atm_no_barrier_store(&c->ref_pair, 1 << INTERNAL_REF_BITS);
284
317
  c->connector = connector;
285
318
  grpc_connector_ref(c->connector);
@@ -293,7 +326,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
293
326
  }
294
327
  c->addr = gpr_malloc(args->addr_len);
295
328
  memcpy(c->addr, args->addr, args->addr_len);
296
- grpc_pollset_set_init(&c->pollset_set);
329
+ c->pollset_set = grpc_pollset_set_create();
297
330
  c->addr_len = args->addr_len;
298
331
  grpc_set_initial_connect_string(&c->addr, &c->addr_len,
299
332
  &c->initial_connect_string);
@@ -305,13 +338,14 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
305
338
  grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
306
339
  "subchannel");
307
340
  gpr_mu_init(&c->mu);
308
- return c;
341
+
342
+ return grpc_subchannel_index_register(exec_ctx, key, c);
309
343
  }
310
344
 
311
345
  static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
312
346
  grpc_connect_in_args args;
313
347
 
314
- args.interested_parties = &c->pollset_set;
348
+ args.interested_parties = c->pollset_set;
315
349
  args.addr = c->addr;
316
350
  args.addr_len = c->addr_len;
317
351
  args.deadline = compute_connect_deadline(c);
@@ -345,7 +379,7 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
345
379
  external_state_watcher *w = arg;
346
380
  grpc_closure *follow_up = w->notify;
347
381
  if (w->pollset_set != NULL) {
348
- grpc_pollset_set_del_pollset_set(exec_ctx, &w->subchannel->pollset_set,
382
+ grpc_pollset_set_del_pollset_set(exec_ctx, w->subchannel->pollset_set,
349
383
  w->pollset_set);
350
384
  }
351
385
  gpr_mu_lock(&w->subchannel->mu);
@@ -361,7 +395,6 @@ void grpc_subchannel_notify_on_state_change(
361
395
  grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
362
396
  grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
363
397
  grpc_closure *notify) {
364
- int do_connect = 0;
365
398
  external_state_watcher *w;
366
399
 
367
400
  if (state == NULL) {
@@ -381,7 +414,7 @@ void grpc_subchannel_notify_on_state_change(
381
414
  w->notify = notify;
382
415
  grpc_closure_init(&w->closure, on_external_state_watcher_done, w);
383
416
  if (interested_parties != NULL) {
384
- grpc_pollset_set_add_pollset_set(exec_ctx, &c->pollset_set,
417
+ grpc_pollset_set_add_pollset_set(exec_ctx, c->pollset_set,
385
418
  interested_parties);
386
419
  }
387
420
  GRPC_SUBCHANNEL_WEAK_REF(c, "external_state_watcher");
@@ -391,17 +424,13 @@ void grpc_subchannel_notify_on_state_change(
391
424
  w->next->prev = w->prev->next = w;
392
425
  if (grpc_connectivity_state_notify_on_state_change(
393
426
  exec_ctx, &c->state_tracker, state, &w->closure)) {
394
- do_connect = 1;
395
427
  c->connecting = 1;
396
428
  /* released by connection */
397
429
  GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
430
+ start_connect(exec_ctx, c);
398
431
  }
399
432
  gpr_mu_unlock(&c->mu);
400
433
  }
401
-
402
- if (do_connect) {
403
- start_connect(exec_ctx, c);
404
- }
405
434
  }
406
435
 
407
436
  void grpc_connected_subchannel_process_transport_op(
@@ -539,7 +568,7 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
539
568
  GRPC_SUBCHANNEL_WEAK_REF(c, "state_watcher");
540
569
  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
541
570
  grpc_connected_subchannel_notify_on_state_change(
542
- exec_ctx, con, &c->pollset_set, &sw_subchannel->connectivity_state,
571
+ exec_ctx, con, c->pollset_set, &sw_subchannel->connectivity_state,
543
572
  &sw_subchannel->closure);
544
573
 
545
574
  /* signal completion */
@@ -601,11 +630,12 @@ static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
601
630
  if (c->disconnected) {
602
631
  iomgr_success = 0;
603
632
  }
604
- gpr_mu_unlock(&c->mu);
605
633
  if (iomgr_success) {
606
634
  update_reconnect_parameters(c);
607
635
  continue_connect(exec_ctx, c);
636
+ gpr_mu_unlock(&c->mu);
608
637
  } else {
638
+ gpr_mu_unlock(&c->mu);
609
639
  GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
610
640
  }
611
641
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  *
3
- * Copyright 2015, Google Inc.
3
+ * Copyright 2015-2016, Google Inc.
4
4
  * All rights reserved.
5
5
  *
6
6
  * Redistribution and use in source and binary forms, with or without
@@ -48,6 +48,8 @@ typedef struct grpc_subchannel_args grpc_subchannel_args;
48
48
  #ifdef GRPC_STREAM_REFCOUNT_DEBUG
49
49
  #define GRPC_SUBCHANNEL_REF(p, r) \
50
50
  grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
51
+ #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
52
+ grpc_subchannel_ref_from_weak_ref((p), __FILE__, __LINE__, (r))
51
53
  #define GRPC_SUBCHANNEL_UNREF(cl, p, r) \
52
54
  grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
53
55
  #define GRPC_SUBCHANNEL_WEAK_REF(p, r) \
@@ -66,6 +68,8 @@ typedef struct grpc_subchannel_args grpc_subchannel_args;
66
68
  , const char *file, int line, const char *reason
67
69
  #else
68
70
  #define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p))
71
+ #define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) \
72
+ grpc_subchannel_ref_from_weak_ref((p))
69
73
  #define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p))
70
74
  #define GRPC_SUBCHANNEL_WEAK_REF(p, r) grpc_subchannel_weak_ref((p))
71
75
  #define GRPC_SUBCHANNEL_WEAK_UNREF(cl, p, r) \
@@ -79,13 +83,15 @@ typedef struct grpc_subchannel_args grpc_subchannel_args;
79
83
  #define GRPC_SUBCHANNEL_REF_EXTRA_ARGS
80
84
  #endif
81
85
 
82
- void grpc_subchannel_ref(grpc_subchannel *channel
83
- GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
86
+ grpc_subchannel *grpc_subchannel_ref(grpc_subchannel *channel
87
+ GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
88
+ grpc_subchannel *grpc_subchannel_ref_from_weak_ref(
89
+ grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
84
90
  void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
85
91
  grpc_subchannel *channel
86
92
  GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
87
- void grpc_subchannel_weak_ref(grpc_subchannel *channel
88
- GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
93
+ grpc_subchannel *grpc_subchannel_weak_ref(grpc_subchannel *channel
94
+ GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
89
95
  void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
90
96
  grpc_subchannel *channel
91
97
  GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
@@ -146,6 +152,8 @@ grpc_call_stack *grpc_subchannel_call_get_call_stack(
146
152
  grpc_subchannel_call *subchannel_call);
147
153
 
148
154
  struct grpc_subchannel_args {
155
+ /* When updating this struct, also update subchannel_index.c */
156
+
149
157
  /** Channel filters for this channel - wrapped factories will likely
150
158
  want to mutate this */
151
159
  const grpc_channel_filter **filters;
@@ -159,7 +167,8 @@ struct grpc_subchannel_args {
159
167
  };
160
168
 
161
169
  /** create a subchannel given a connector */
162
- grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
170
+ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
171
+ grpc_connector *connector,
163
172
  grpc_subchannel_args *args);
164
173
 
165
174
  #endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_H */
@@ -0,0 +1,261 @@
1
+ //
2
+ //
3
+ // Copyright 2016, 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
+
34
+ #include "src/core/client_config/subchannel_index.h"
35
+
36
+ #include <stdbool.h>
37
+ #include <string.h>
38
+
39
+ #include <grpc/support/alloc.h>
40
+ #include <grpc/support/avl.h>
41
+ #include <grpc/support/tls.h>
42
+
43
+ #include "src/core/channel/channel_args.h"
44
+
45
+ // a map of subchannel_key --> subchannel, used for detecting connections
46
+ // to the same destination in order to share them
47
+ static gpr_avl g_subchannel_index;
48
+
49
+ static gpr_mu g_mu;
50
+
51
+ struct grpc_subchannel_key {
52
+ grpc_connector *connector;
53
+ grpc_subchannel_args args;
54
+ };
55
+
56
+ GPR_TLS_DECL(subchannel_index_exec_ctx);
57
+
58
+ static void enter_ctx(grpc_exec_ctx *exec_ctx) {
59
+ GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == 0);
60
+ gpr_tls_set(&subchannel_index_exec_ctx, (intptr_t)exec_ctx);
61
+ }
62
+
63
+ static void leave_ctx(grpc_exec_ctx *exec_ctx) {
64
+ GPR_ASSERT(gpr_tls_get(&subchannel_index_exec_ctx) == (intptr_t)exec_ctx);
65
+ gpr_tls_set(&subchannel_index_exec_ctx, 0);
66
+ }
67
+
68
+ static grpc_exec_ctx *current_ctx() {
69
+ grpc_exec_ctx *c = (grpc_exec_ctx *)gpr_tls_get(&subchannel_index_exec_ctx);
70
+ GPR_ASSERT(c != NULL);
71
+ return c;
72
+ }
73
+
74
+ static grpc_subchannel_key *create_key(
75
+ grpc_connector *connector, grpc_subchannel_args *args,
76
+ grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) {
77
+ grpc_subchannel_key *k = gpr_malloc(sizeof(*k));
78
+ k->connector = grpc_connector_ref(connector);
79
+ k->args.filter_count = args->filter_count;
80
+ k->args.filters = gpr_malloc(sizeof(*k->args.filters) * k->args.filter_count);
81
+ memcpy((grpc_channel_filter *)k->args.filters, args->filters,
82
+ sizeof(*k->args.filters) * k->args.filter_count);
83
+ k->args.addr_len = args->addr_len;
84
+ k->args.addr = gpr_malloc(args->addr_len);
85
+ memcpy(k->args.addr, args->addr, k->args.addr_len);
86
+ k->args.args = copy_channel_args(args->args);
87
+ return k;
88
+ }
89
+
90
+ grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector,
91
+ grpc_subchannel_args *args) {
92
+ return create_key(connector, args, grpc_channel_args_normalize);
93
+ }
94
+
95
+ static grpc_subchannel_key *subchannel_key_copy(grpc_subchannel_key *k) {
96
+ return create_key(k->connector, &k->args, grpc_channel_args_copy);
97
+ }
98
+
99
+ static int subchannel_key_compare(grpc_subchannel_key *a,
100
+ grpc_subchannel_key *b) {
101
+ int c = GPR_ICMP(a->connector, b->connector);
102
+ if (c != 0) return c;
103
+ c = GPR_ICMP(a->args.addr_len, b->args.addr_len);
104
+ if (c != 0) return c;
105
+ c = GPR_ICMP(a->args.filter_count, b->args.filter_count);
106
+ if (c != 0) return c;
107
+ c = memcmp(a->args.addr, b->args.addr, a->args.addr_len);
108
+ if (c != 0) return c;
109
+ c = memcmp(a->args.filters, b->args.filters,
110
+ a->args.filter_count * sizeof(*a->args.filters));
111
+ return grpc_channel_args_compare(a->args.args, b->args.args);
112
+ }
113
+
114
+ void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
115
+ grpc_subchannel_key *k) {
116
+ grpc_connector_unref(exec_ctx, k->connector);
117
+ gpr_free(k->args.addr);
118
+ gpr_free((grpc_channel_args *)k->args.filters);
119
+ grpc_channel_args_destroy((grpc_channel_args *)k->args.args);
120
+ gpr_free(k);
121
+ }
122
+
123
+ static void sck_avl_destroy(void *p) {
124
+ grpc_subchannel_key_destroy(current_ctx(), p);
125
+ }
126
+
127
+ static void *sck_avl_copy(void *p) { return subchannel_key_copy(p); }
128
+
129
+ static long sck_avl_compare(void *a, void *b) {
130
+ return subchannel_key_compare(a, b);
131
+ }
132
+
133
+ static void scv_avl_destroy(void *p) {
134
+ GRPC_SUBCHANNEL_WEAK_UNREF(current_ctx(), p, "subchannel_index");
135
+ }
136
+
137
+ static void *scv_avl_copy(void *p) {
138
+ GRPC_SUBCHANNEL_WEAK_REF(p, "subchannel_index");
139
+ return p;
140
+ }
141
+
142
+ static const gpr_avl_vtable subchannel_avl_vtable = {
143
+ .destroy_key = sck_avl_destroy,
144
+ .copy_key = sck_avl_copy,
145
+ .compare_keys = sck_avl_compare,
146
+ .destroy_value = scv_avl_destroy,
147
+ .copy_value = scv_avl_copy};
148
+
149
+ void grpc_subchannel_index_init(void) {
150
+ g_subchannel_index = gpr_avl_create(&subchannel_avl_vtable);
151
+ gpr_mu_init(&g_mu);
152
+ gpr_tls_init(&subchannel_index_exec_ctx);
153
+ }
154
+
155
+ void grpc_subchannel_index_shutdown(void) {
156
+ gpr_mu_destroy(&g_mu);
157
+ gpr_avl_unref(g_subchannel_index);
158
+ gpr_tls_destroy(&subchannel_index_exec_ctx);
159
+ }
160
+
161
+ grpc_subchannel *grpc_subchannel_index_find(grpc_exec_ctx *exec_ctx,
162
+ grpc_subchannel_key *key) {
163
+ enter_ctx(exec_ctx);
164
+
165
+ // Lock, and take a reference to the subchannel index.
166
+ // We don't need to do the search under a lock as avl's are immutable.
167
+ gpr_mu_lock(&g_mu);
168
+ gpr_avl index = gpr_avl_ref(g_subchannel_index);
169
+ gpr_mu_unlock(&g_mu);
170
+
171
+ grpc_subchannel *c =
172
+ GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(gpr_avl_get(index, key), "index_find");
173
+ gpr_avl_unref(index);
174
+
175
+ leave_ctx(exec_ctx);
176
+ return c;
177
+ }
178
+
179
+ grpc_subchannel *grpc_subchannel_index_register(grpc_exec_ctx *exec_ctx,
180
+ grpc_subchannel_key *key,
181
+ grpc_subchannel *constructed) {
182
+ enter_ctx(exec_ctx);
183
+
184
+ grpc_subchannel *c = NULL;
185
+
186
+ while (c == NULL) {
187
+ // Compare and swap loop:
188
+ // - take a reference to the current index
189
+ gpr_mu_lock(&g_mu);
190
+ gpr_avl index = gpr_avl_ref(g_subchannel_index);
191
+ gpr_mu_unlock(&g_mu);
192
+
193
+ // - Check to see if a subchannel already exists
194
+ c = gpr_avl_get(index, key);
195
+ if (c != NULL) {
196
+ // yes -> we're done
197
+ GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, constructed, "index_register");
198
+ } else {
199
+ // no -> update the avl and compare/swap
200
+ gpr_avl updated =
201
+ gpr_avl_add(gpr_avl_ref(index), subchannel_key_copy(key),
202
+ GRPC_SUBCHANNEL_WEAK_REF(constructed, "index_register"));
203
+
204
+ // it may happen (but it's expected to be unlikely)
205
+ // that some other thread has changed the index:
206
+ // compare/swap here to check that, and retry as necessary
207
+ gpr_mu_lock(&g_mu);
208
+ if (index.root == g_subchannel_index.root) {
209
+ GPR_SWAP(gpr_avl, updated, g_subchannel_index);
210
+ c = constructed;
211
+ }
212
+ gpr_mu_unlock(&g_mu);
213
+
214
+ gpr_avl_unref(updated);
215
+ }
216
+ gpr_avl_unref(index);
217
+ }
218
+
219
+ leave_ctx(exec_ctx);
220
+
221
+ return c;
222
+ }
223
+
224
+ void grpc_subchannel_index_unregister(grpc_exec_ctx *exec_ctx,
225
+ grpc_subchannel_key *key,
226
+ grpc_subchannel *constructed) {
227
+ enter_ctx(exec_ctx);
228
+
229
+ bool done = false;
230
+ while (!done) {
231
+ // Compare and swap loop:
232
+ // - take a reference to the current index
233
+ gpr_mu_lock(&g_mu);
234
+ gpr_avl index = gpr_avl_ref(g_subchannel_index);
235
+ gpr_mu_unlock(&g_mu);
236
+
237
+ // Check to see if this key still refers to the previously
238
+ // registered subchannel
239
+ grpc_subchannel *c = gpr_avl_get(index, key);
240
+ if (c != constructed) {
241
+ gpr_avl_unref(index);
242
+ break;
243
+ }
244
+
245
+ // compare and swap the update (some other thread may have
246
+ // mutated the index behind us)
247
+ gpr_avl updated = gpr_avl_remove(gpr_avl_ref(index), key);
248
+
249
+ gpr_mu_lock(&g_mu);
250
+ if (index.root == g_subchannel_index.root) {
251
+ GPR_SWAP(gpr_avl, updated, g_subchannel_index);
252
+ done = true;
253
+ }
254
+ gpr_mu_unlock(&g_mu);
255
+
256
+ gpr_avl_unref(updated);
257
+ gpr_avl_unref(index);
258
+ }
259
+
260
+ leave_ctx(exec_ctx);
261
+ }