grpc 1.3.4 → 1.4.0

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 (286) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +581 -450
  3. data/include/grpc/census.h +49 -49
  4. data/include/grpc/grpc.h +16 -70
  5. data/include/grpc/grpc_security.h +59 -59
  6. data/include/grpc/grpc_security_constants.h +9 -9
  7. data/include/grpc/impl/codegen/atm.h +1 -1
  8. data/include/grpc/impl/codegen/atm_windows.h +4 -4
  9. data/include/grpc/impl/codegen/byte_buffer_reader.h +2 -2
  10. data/include/grpc/impl/codegen/compression_types.h +4 -5
  11. data/include/grpc/impl/codegen/gpr_slice.h +5 -5
  12. data/include/grpc/impl/codegen/gpr_types.h +6 -7
  13. data/include/grpc/impl/codegen/grpc_types.h +128 -59
  14. data/include/grpc/impl/codegen/port_platform.h +6 -0
  15. data/include/grpc/impl/codegen/propagation_bits.h +2 -2
  16. data/include/grpc/impl/codegen/slice.h +13 -12
  17. data/include/grpc/impl/codegen/status.h +23 -18
  18. data/include/grpc/impl/codegen/sync.h +1 -1
  19. data/include/grpc/load_reporting.h +6 -6
  20. data/include/grpc/slice.h +47 -25
  21. data/include/grpc/slice_buffer.h +18 -14
  22. data/include/grpc/support/alloc.h +7 -7
  23. data/include/grpc/support/cmdline.h +10 -10
  24. data/include/grpc/support/cpu.h +3 -3
  25. data/include/grpc/support/histogram.h +1 -1
  26. data/include/grpc/support/host_port.h +2 -2
  27. data/include/grpc/support/log.h +9 -9
  28. data/include/grpc/support/log_windows.h +1 -1
  29. data/include/grpc/support/string_util.h +3 -3
  30. data/include/grpc/support/subprocess.h +3 -3
  31. data/include/grpc/support/sync.h +31 -31
  32. data/include/grpc/support/thd.h +11 -11
  33. data/include/grpc/support/time.h +12 -12
  34. data/include/grpc/support/tls.h +1 -1
  35. data/include/grpc/support/tls_gcc.h +2 -2
  36. data/include/grpc/support/tls_msvc.h +1 -1
  37. data/include/grpc/support/tls_pthread.h +1 -1
  38. data/include/grpc/support/useful.h +2 -2
  39. data/include/grpc/support/workaround_list.h +46 -0
  40. data/src/core/ext/census/context.c +1 -1
  41. data/src/core/ext/census/intrusive_hash_map.c +319 -0
  42. data/src/core/ext/census/intrusive_hash_map.h +167 -0
  43. data/src/core/ext/census/intrusive_hash_map_internal.h +63 -0
  44. data/src/core/ext/census/resource.c +3 -1
  45. data/src/core/ext/filters/client_channel/channel_connectivity.c +1 -1
  46. data/src/core/ext/filters/client_channel/client_channel.c +173 -103
  47. data/src/core/ext/filters/client_channel/client_channel_plugin.c +3 -2
  48. data/src/core/ext/filters/client_channel/lb_policy.c +2 -1
  49. data/src/core/ext/filters/client_channel/lb_policy.h +8 -7
  50. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +153 -0
  51. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +42 -0
  52. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +405 -102
  53. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +133 -0
  54. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +65 -0
  55. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +90 -51
  56. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +7 -1
  57. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +19 -8
  58. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +63 -34
  59. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +2 -1
  60. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +188 -294
  61. data/src/core/ext/filters/client_channel/lb_policy_factory.c +28 -5
  62. data/src/core/ext/filters/client_channel/lb_policy_factory.h +18 -4
  63. data/src/core/ext/filters/client_channel/parse_address.c +90 -59
  64. data/src/core/ext/filters/client_channel/parse_address.h +17 -8
  65. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c +11 -7
  66. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c +59 -14
  67. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +6 -0
  68. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c +3 -3
  69. data/src/core/ext/filters/client_channel/subchannel.c +20 -17
  70. data/src/core/ext/filters/client_channel/subchannel.h +1 -0
  71. data/src/core/ext/filters/client_channel/subchannel_index.c +11 -1
  72. data/src/core/ext/filters/client_channel/uri_parser.c +36 -22
  73. data/src/core/ext/filters/client_channel/uri_parser.h +1 -1
  74. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.c +42 -17
  75. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.h +8 -9
  76. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.c +19 -11
  77. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.h +3 -6
  78. data/src/core/ext/filters/http/http_filters_plugin.c +104 -0
  79. data/src/core/{lib/channel/compress_filter.c → ext/filters/http/message_compress/message_compress_filter.c} +124 -23
  80. data/src/core/{lib/channel/compress_filter.h → ext/filters/http/message_compress/message_compress_filter.h} +5 -6
  81. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.c +4 -6
  82. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.h +3 -3
  83. data/src/core/ext/filters/load_reporting/load_reporting.c +2 -25
  84. data/src/core/ext/filters/load_reporting/load_reporting_filter.c +26 -1
  85. data/src/core/ext/filters/max_age/max_age_filter.c +14 -14
  86. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.c +91 -47
  87. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.h +3 -3
  88. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +223 -0
  89. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h +40 -0
  90. data/src/core/ext/filters/workarounds/workaround_utils.c +65 -0
  91. data/src/core/ext/filters/workarounds/workaround_utils.h +52 -0
  92. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
  93. data/src/core/ext/transport/chttp2/server/chttp2_server.c +3 -2
  94. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +2 -2
  95. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +3 -3
  96. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +319 -175
  97. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -2
  98. data/src/core/ext/transport/chttp2/transport/frame_data.c +203 -164
  99. data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -14
  100. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +1 -1
  101. data/src/core/ext/transport/chttp2/transport/frame_ping.c +1 -1
  102. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
  103. data/src/core/ext/transport/chttp2/transport/frame_settings.c +5 -5
  104. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +1 -1
  105. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +4 -4
  106. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +2 -4
  107. data/src/core/ext/transport/chttp2/transport/hpack_table.c +4 -3
  108. data/src/core/ext/transport/chttp2/transport/internal.h +50 -33
  109. data/src/core/ext/transport/chttp2/transport/parsing.c +10 -11
  110. data/src/core/ext/transport/chttp2/transport/writing.c +32 -13
  111. data/src/core/lib/channel/channel_args.c +30 -9
  112. data/src/core/lib/channel/channel_args.h +5 -1
  113. data/src/core/lib/channel/channel_stack.c +1 -1
  114. data/src/core/lib/channel/channel_stack.h +2 -2
  115. data/src/core/lib/channel/channel_stack_builder.c +13 -1
  116. data/src/core/lib/channel/channel_stack_builder.h +5 -1
  117. data/src/core/lib/channel/connected_channel.c +3 -1
  118. data/src/core/lib/channel/context.h +2 -2
  119. data/src/core/lib/compression/message_compress.c +2 -2
  120. data/src/core/lib/debug/trace.c +13 -6
  121. data/src/core/lib/debug/trace.h +27 -1
  122. data/src/core/lib/http/httpcli.c +1 -1
  123. data/src/core/lib/http/httpcli_security_connector.c +9 -11
  124. data/src/core/lib/http/parser.c +2 -2
  125. data/src/core/lib/http/parser.h +2 -1
  126. data/src/core/lib/iomgr/combiner.c +6 -6
  127. data/src/core/lib/iomgr/combiner.h +2 -1
  128. data/src/core/lib/iomgr/error.c +12 -5
  129. data/src/core/lib/iomgr/error.h +13 -13
  130. data/src/core/lib/iomgr/ev_epoll1_linux.c +984 -0
  131. data/src/core/lib/iomgr/ev_epoll1_linux.h +44 -0
  132. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +2146 -0
  133. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h +43 -0
  134. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +1337 -0
  135. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h +43 -0
  136. data/src/core/lib/iomgr/ev_epollex_linux.c +1511 -0
  137. data/src/core/lib/iomgr/ev_epollex_linux.h +43 -0
  138. data/src/core/lib/iomgr/{ev_epoll_linux.c → ev_epollsig_linux.c} +41 -33
  139. data/src/core/lib/iomgr/{ev_epoll_linux.h → ev_epollsig_linux.h} +4 -4
  140. data/src/core/lib/iomgr/ev_poll_posix.c +12 -27
  141. data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
  142. data/src/core/lib/iomgr/ev_posix.c +22 -8
  143. data/src/core/lib/iomgr/ev_posix.h +4 -3
  144. data/src/core/lib/iomgr/ev_windows.c +43 -0
  145. data/src/core/lib/iomgr/exec_ctx.c +5 -0
  146. data/src/core/lib/iomgr/exec_ctx.h +2 -0
  147. data/src/core/lib/iomgr/iomgr.c +4 -0
  148. data/src/core/lib/iomgr/iomgr.h +3 -0
  149. data/src/core/lib/iomgr/is_epollexclusive_available.c +116 -0
  150. data/src/core/lib/iomgr/is_epollexclusive_available.h +41 -0
  151. data/src/core/lib/iomgr/lockfree_event.c +16 -0
  152. data/src/core/lib/iomgr/pollset.h +2 -5
  153. data/src/core/lib/iomgr/pollset_uv.c +1 -1
  154. data/src/core/lib/iomgr/pollset_windows.c +3 -3
  155. data/src/core/lib/iomgr/resource_quota.c +9 -8
  156. data/src/core/lib/iomgr/resource_quota.h +2 -1
  157. data/src/core/lib/iomgr/sockaddr_utils.h +1 -1
  158. data/src/core/lib/iomgr/socket_mutator.h +2 -0
  159. data/src/core/lib/iomgr/sys_epoll_wrapper.h +43 -0
  160. data/src/core/lib/iomgr/tcp_client_posix.c +6 -6
  161. data/src/core/lib/iomgr/tcp_client_uv.c +3 -3
  162. data/src/core/lib/iomgr/tcp_posix.c +7 -7
  163. data/src/core/lib/iomgr/tcp_posix.h +2 -1
  164. data/src/core/lib/iomgr/tcp_server_posix.c +1 -1
  165. data/src/core/lib/iomgr/tcp_uv.c +6 -6
  166. data/src/core/lib/iomgr/tcp_uv.h +2 -1
  167. data/src/core/lib/iomgr/tcp_windows.c +1 -1
  168. data/src/core/lib/iomgr/timer_generic.c +24 -25
  169. data/src/core/lib/iomgr/timer_manager.c +276 -0
  170. data/src/core/lib/iomgr/timer_manager.h +52 -0
  171. data/src/core/lib/iomgr/timer_uv.c +6 -0
  172. data/src/core/lib/iomgr/udp_server.c +42 -9
  173. data/src/core/lib/iomgr/udp_server.h +3 -1
  174. data/src/core/lib/security/credentials/credentials.c +0 -1
  175. data/src/core/lib/security/credentials/fake/fake_credentials.c +23 -0
  176. data/src/core/lib/security/credentials/fake/fake_credentials.h +12 -9
  177. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +1 -1
  178. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -1
  179. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +1 -1
  180. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +24 -53
  181. data/src/core/lib/security/transport/client_auth_filter.c +9 -3
  182. data/src/core/lib/security/transport/secure_endpoint.c +7 -7
  183. data/src/core/lib/security/transport/secure_endpoint.h +1 -1
  184. data/src/core/lib/security/transport/security_connector.c +45 -57
  185. data/src/core/lib/security/transport/security_connector.h +10 -14
  186. data/src/core/lib/security/transport/security_handshaker.c +123 -97
  187. data/src/core/lib/slice/b64.c +1 -1
  188. data/src/core/lib/slice/percent_encoding.c +3 -3
  189. data/src/core/lib/slice/slice.c +66 -33
  190. data/src/core/lib/slice/slice_buffer.c +25 -6
  191. data/src/core/lib/slice/slice_hash_table.c +33 -35
  192. data/src/core/lib/slice/slice_hash_table.h +7 -12
  193. data/src/core/lib/support/atomic.h +45 -0
  194. data/src/core/lib/support/atomic_with_atm.h +70 -0
  195. data/src/core/lib/support/atomic_with_std.h +48 -0
  196. data/src/core/lib/support/avl.c +14 -14
  197. data/src/core/lib/support/cmdline.c +3 -3
  198. data/src/core/lib/support/histogram.c +2 -2
  199. data/src/core/lib/support/host_port.c +1 -1
  200. data/src/core/lib/support/memory.h +74 -0
  201. data/src/core/lib/support/mpscq.c +36 -2
  202. data/src/core/lib/support/mpscq.h +28 -1
  203. data/src/core/lib/support/stack_lockfree.c +3 -36
  204. data/src/core/lib/support/string.c +12 -12
  205. data/src/core/lib/support/string_posix.c +1 -1
  206. data/src/core/lib/support/subprocess_posix.c +2 -2
  207. data/src/core/lib/support/thd_posix.c +1 -1
  208. data/src/core/lib/support/time_posix.c +8 -0
  209. data/src/core/lib/support/tmpfile_posix.c +10 -10
  210. data/src/core/lib/surface/alarm.c +3 -1
  211. data/src/core/lib/surface/api_trace.c +2 -1
  212. data/src/core/lib/surface/api_trace.h +2 -2
  213. data/src/core/lib/surface/byte_buffer_reader.c +1 -1
  214. data/src/core/lib/surface/call.c +65 -22
  215. data/src/core/lib/surface/call.h +4 -2
  216. data/src/core/lib/surface/channel_init.c +2 -19
  217. data/src/core/lib/surface/channel_stack_type.c +18 -0
  218. data/src/core/lib/surface/channel_stack_type.h +2 -0
  219. data/src/core/lib/surface/completion_queue.c +694 -247
  220. data/src/core/lib/surface/completion_queue.h +30 -13
  221. data/src/core/lib/surface/completion_queue_factory.c +24 -9
  222. data/src/core/lib/surface/init.c +1 -52
  223. data/src/core/lib/surface/{lame_client.c → lame_client.cc} +37 -26
  224. data/src/core/lib/surface/server.c +79 -110
  225. data/src/core/lib/surface/server.h +2 -1
  226. data/src/core/lib/surface/version.c +2 -2
  227. data/src/core/lib/transport/bdp_estimator.c +25 -9
  228. data/src/core/lib/transport/bdp_estimator.h +7 -1
  229. data/src/core/lib/transport/byte_stream.c +23 -9
  230. data/src/core/lib/transport/byte_stream.h +15 -6
  231. data/src/core/lib/transport/connectivity_state.c +6 -6
  232. data/src/core/lib/transport/connectivity_state.h +2 -1
  233. data/src/core/lib/transport/service_config.c +6 -13
  234. data/src/core/lib/transport/service_config.h +2 -2
  235. data/src/core/lib/transport/static_metadata.c +403 -389
  236. data/src/core/lib/transport/static_metadata.h +127 -114
  237. data/src/core/plugin_registry/grpc_plugin_registry.c +16 -0
  238. data/src/core/tsi/fake_transport_security.c +5 -4
  239. data/src/core/tsi/ssl_transport_security.c +71 -82
  240. data/src/core/tsi/ssl_transport_security.h +39 -61
  241. data/src/core/tsi/transport_security.c +83 -2
  242. data/src/core/tsi/transport_security.h +27 -2
  243. data/src/core/tsi/transport_security_adapter.c +236 -0
  244. data/src/core/tsi/transport_security_adapter.h +62 -0
  245. data/src/core/tsi/transport_security_interface.h +179 -66
  246. data/src/ruby/ext/grpc/extconf.rb +2 -1
  247. data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -6
  248. data/src/ruby/ext/grpc/rb_call.c +56 -48
  249. data/src/ruby/ext/grpc/rb_call.h +3 -4
  250. data/src/ruby/ext/grpc/rb_call_credentials.c +23 -22
  251. data/src/ruby/ext/grpc/rb_channel.c +2 -3
  252. data/src/ruby/ext/grpc/rb_channel_args.c +11 -9
  253. data/src/ruby/ext/grpc/rb_channel_credentials.c +16 -12
  254. data/src/ruby/ext/grpc/rb_completion_queue.c +7 -9
  255. data/src/ruby/ext/grpc/rb_compression_options.c +7 -6
  256. data/src/ruby/ext/grpc/rb_event_thread.c +10 -12
  257. data/src/ruby/ext/grpc/rb_event_thread.h +1 -2
  258. data/src/ruby/ext/grpc/rb_grpc.c +11 -15
  259. data/src/ruby/ext/grpc/rb_grpc.h +2 -2
  260. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +16 -6
  261. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +25 -10
  262. data/src/ruby/ext/grpc/rb_server.c +26 -28
  263. data/src/ruby/lib/grpc/grpc.rb +1 -1
  264. data/src/ruby/lib/grpc/version.rb +1 -1
  265. data/third_party/cares/config_linux/ares_config.h +36 -2
  266. data/third_party/zlib/adler32.c +14 -7
  267. data/third_party/zlib/compress.c +24 -18
  268. data/third_party/zlib/crc32.c +29 -12
  269. data/third_party/zlib/deflate.c +499 -303
  270. data/third_party/zlib/deflate.h +19 -16
  271. data/third_party/zlib/gzguts.h +16 -7
  272. data/third_party/zlib/gzlib.c +17 -14
  273. data/third_party/zlib/gzread.c +108 -48
  274. data/third_party/zlib/gzwrite.c +210 -122
  275. data/third_party/zlib/infback.c +2 -2
  276. data/third_party/zlib/inffast.c +34 -51
  277. data/third_party/zlib/inflate.c +86 -37
  278. data/third_party/zlib/inflate.h +7 -4
  279. data/third_party/zlib/inftrees.c +12 -14
  280. data/third_party/zlib/trees.c +38 -61
  281. data/third_party/zlib/uncompr.c +66 -32
  282. data/third_party/zlib/zconf.h +32 -9
  283. data/third_party/zlib/zlib.h +298 -154
  284. data/third_party/zlib/zutil.c +25 -24
  285. data/third_party/zlib/zutil.h +35 -17
  286. metadata +63 -30
@@ -0,0 +1,167 @@
1
+ /*
2
+ *
3
+ * Copyright 2017, 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
+ #ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
35
+ #define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
36
+
37
+ #include "src/core/ext/census/intrusive_hash_map_internal.h"
38
+
39
+ /* intrusive_hash_map is a fast chained hash table. This hash map is faster than
40
+ * a dense hash map when the application calls insert and erase more often than
41
+ * find. When the workload is dominated by find() a dense hash map may be
42
+ * faster.
43
+ *
44
+ * intrusive_hash_map uses an intrusive header placed within a user defined
45
+ * struct. The header field IHM_key MUST be set to a valid value before
46
+ * insertion into the hash map or undefined behavior may occur. The header field
47
+ * IHM_hash_link MUST to be set to NULL initially.
48
+ *
49
+ * EXAMPLE USAGE:
50
+ *
51
+ * typedef struct string_item {
52
+ * INTRUSIVE_HASH_MAP_HEADER;
53
+ * // User data.
54
+ * char *str_buf;
55
+ * uint16_t len;
56
+ * } string_item;
57
+ *
58
+ * static string_item *make_string_item(uint64_t key, const char *buf,
59
+ * uint16_t len) {
60
+ * string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
61
+ * item->IHM_key = key;
62
+ * item->IHM_hash_link = NULL;
63
+ * item->len = len;
64
+ * item->str_buf = (char *)malloc(len);
65
+ * memcpy(item->str_buf, buf, len);
66
+ * return item;
67
+ * }
68
+ *
69
+ * intrusive_hash_map hash_map;
70
+ * intrusive_hash_map_init(&hash_map, 4);
71
+ * string_item *new_item1 = make_string_item(10, "test1", 5);
72
+ * bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
73
+ *
74
+ * string_item *item1 =
75
+ * (string_item *)intrusive_hash_map_find(&hash_map, 10);
76
+ */
77
+
78
+ /* Hash map item. Stores key and a pointer to the actual object. A user defined
79
+ * version of this can be passed in provided the first 2 entries (key and
80
+ * hash_link) are the same. These entries must be first in the user defined
81
+ * struct. Pointer to struct will need to be cast as (hm_item *) when passed to
82
+ * hash map. This allows it to be intrusive. */
83
+ typedef struct hm_item {
84
+ uint64_t key;
85
+ struct hm_item *hash_link;
86
+ /* Optional user defined data after this. */
87
+ } hm_item;
88
+
89
+ /* Macro provided for ease of use. This must be first in the user defined
90
+ * struct (i.e. uint64_t key and hm_item * must be the first two elements in
91
+ * that order). */
92
+ #define INTRUSIVE_HASH_MAP_HEADER \
93
+ uint64_t IHM_key; \
94
+ struct hm_item *IHM_hash_link
95
+
96
+ /* Index struct which acts as a pseudo-iterator within the hash map. */
97
+ typedef struct hm_index {
98
+ uint32_t bucket_index; // hash map bucket index.
99
+ hm_item *item; // Pointer to hm_item within the hash map.
100
+ } hm_index;
101
+
102
+ /* Returns true if two hm_indices point to the same object within the hash map
103
+ * and false otherwise. */
104
+ inline bool hm_index_compare(const hm_index *A, const hm_index *B) {
105
+ return (A->item == B->item && A->bucket_index == B->bucket_index);
106
+ }
107
+
108
+ /*
109
+ * Helper functions for iterating over the hash map.
110
+ */
111
+
112
+ /* On return idx will contain an invalid index which is always equal to
113
+ * hash_map->buckets.size_ */
114
+ void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx);
115
+
116
+ /* Iterates index to the next valid entry in the hash map and stores the
117
+ * index within idx. If end of table is reached, idx will contain the same
118
+ * values as if intrusive_hash_map_end() was called. */
119
+ void intrusive_hash_map_next(const intrusive_hash_map *hash_map, hm_index *idx);
120
+
121
+ /* On return, idx will contain the index of the first non-null entry in the hash
122
+ * map. If the hash map is empty, idx will contain the same values as if
123
+ * intrusive_hash_map_end() was called. */
124
+ void intrusive_hash_map_begin(const intrusive_hash_map *hash_map,
125
+ hm_index *idx);
126
+
127
+ /* Initialize intrusive hash map data structure. This must be called before
128
+ * the hash map can be used. The initial size of an intrusive hash map will be
129
+ * 2^initial_log2_map_size (valid range is [0, 31]). */
130
+ void intrusive_hash_map_init(intrusive_hash_map *hash_map,
131
+ uint32_t initial_log2_map_size);
132
+
133
+ /* Returns true if the hash map is empty and false otherwise. */
134
+ bool intrusive_hash_map_empty(const intrusive_hash_map *hash_map);
135
+
136
+ /* Returns the number of elements currently in the hash map. */
137
+ size_t intrusive_hash_map_size(const intrusive_hash_map *hash_map);
138
+
139
+ /* Find a hm_item within the hash map by key. Returns NULL if item was not
140
+ * found. */
141
+ hm_item *intrusive_hash_map_find(const intrusive_hash_map *hash_map,
142
+ uint64_t key);
143
+
144
+ /* Erase the hm_item that corresponds with key. If the hm_item is found, return
145
+ * the pointer to the hm_item. Else returns NULL. */
146
+ hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key);
147
+
148
+ /* Attempts to insert a new hm_item into the hash map. If an element with the
149
+ * same key already exists, it will not insert the new item and return false.
150
+ * Otherwise, it will insert the new item and return true. */
151
+ bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item);
152
+
153
+ /* Clears entire contents of the hash map, but leaves internal data structure
154
+ * untouched. Second argument takes a function pointer to a function that will
155
+ * free the object designated by the user and pointed to by hash_map->value. */
156
+ void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
157
+ void (*free_object)(void *));
158
+
159
+ /* Erase all contents of hash map and free the memory. Hash map is invalid
160
+ * after calling this function and cannot be used until it has been
161
+ * reinitialized (intrusive_hash_map_init()). This function takes a function
162
+ * pointer to a function that will free the object designated by the user and
163
+ * pointed to by hash_map->value. */
164
+ void intrusive_hash_map_free(intrusive_hash_map *hash_map,
165
+ void (*free_object)(void *));
166
+
167
+ #endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H */
@@ -0,0 +1,63 @@
1
+ /*
2
+ *
3
+ * Copyright 2017, 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
+ #ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
35
+ #define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
36
+
37
+ #include <grpc/support/alloc.h>
38
+ #include <grpc/support/log.h>
39
+ #include <grpc/support/useful.h>
40
+ #include <stdbool.h>
41
+
42
+ /* The chunked vector is a data structure that allocates buckets for use in the
43
+ * hash map. ChunkedVector is logically equivalent to T*[N] (cast void* as
44
+ * T*). It's internally implemented as an array of 1MB arrays to avoid
45
+ * allocating large consecutive memory chunks. This is an internal data
46
+ * structure that should never be accessed directly. */
47
+ typedef struct chunked_vector {
48
+ size_t size_;
49
+ void **first_;
50
+ void ***rest_;
51
+ } chunked_vector;
52
+
53
+ /* Core intrusive hash map data structure. All internal elements are managed by
54
+ * functions and should not be altered manually. */
55
+ typedef struct intrusive_hash_map {
56
+ uint32_t num_items;
57
+ uint32_t extend_threshold;
58
+ uint32_t log2_num_buckets;
59
+ uint32_t hash_mask;
60
+ chunked_vector buckets;
61
+ } intrusive_hash_map;
62
+
63
+ #endif /* GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H */
@@ -223,7 +223,9 @@ size_t allocate_resource(void) {
223
223
  if (n_resources == n_defined_resources) {
224
224
  size_t new_n_resources = n_resources ? n_resources * 2 : 2;
225
225
  resource **new_resources = gpr_malloc(new_n_resources * sizeof(resource *));
226
- memcpy(new_resources, resources, n_resources * sizeof(resource *));
226
+ if (n_resources != 0) {
227
+ memcpy(new_resources, resources, n_resources * sizeof(resource *));
228
+ }
227
229
  memset(new_resources + n_resources, 0,
228
230
  (new_n_resources - n_resources) * sizeof(resource *));
229
231
  gpr_free(resources);
@@ -134,7 +134,7 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w,
134
134
  gpr_mu_lock(&w->mu);
135
135
 
136
136
  if (due_to_completion) {
137
- if (grpc_trace_operation_failures) {
137
+ if (GRPC_TRACER_ON(grpc_trace_operation_failures)) {
138
138
  GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error));
139
139
  }
140
140
  GRPC_ERROR_UNREF(error);
@@ -49,9 +49,9 @@
49
49
  #include "src/core/ext/filters/client_channel/resolver_registry.h"
50
50
  #include "src/core/ext/filters/client_channel/retry_throttle.h"
51
51
  #include "src/core/ext/filters/client_channel/subchannel.h"
52
+ #include "src/core/ext/filters/deadline/deadline_filter.h"
52
53
  #include "src/core/lib/channel/channel_args.h"
53
54
  #include "src/core/lib/channel/connected_channel.h"
54
- #include "src/core/lib/channel/deadline_filter.h"
55
55
  #include "src/core/lib/iomgr/combiner.h"
56
56
  #include "src/core/lib/iomgr/iomgr.h"
57
57
  #include "src/core/lib/iomgr/polling_entity.h"
@@ -96,17 +96,10 @@ static void method_parameters_unref(method_parameters *method_params) {
96
96
  }
97
97
  }
98
98
 
99
- static void *method_parameters_copy(void *value) {
100
- return method_parameters_ref(value);
101
- }
102
-
103
99
  static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
104
100
  method_parameters_unref(value);
105
101
  }
106
102
 
107
- static const grpc_slice_hash_table_vtable method_parameters_vtable = {
108
- method_parameters_free, method_parameters_copy};
109
-
110
103
  static bool parse_wait_for_ready(grpc_json *field,
111
104
  wait_for_ready_value *wait_for_ready) {
112
105
  if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
@@ -185,6 +178,8 @@ typedef struct client_channel_channel_data {
185
178
  grpc_resolver *resolver;
186
179
  /** have we started resolving this channel */
187
180
  bool started_resolving;
181
+ /** is deadline checking enabled? */
182
+ bool deadline_checking_enabled;
188
183
  /** client channel factory */
189
184
  grpc_client_channel_factory *client_channel_factory;
190
185
 
@@ -243,14 +238,23 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
243
238
  grpc_connectivity_state state,
244
239
  grpc_error *error,
245
240
  const char *reason) {
246
- if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
247
- state == GRPC_CHANNEL_SHUTDOWN) &&
248
- chand->lb_policy != NULL) {
249
- /* cancel picks with wait_for_ready=false */
250
- grpc_lb_policy_cancel_picks_locked(
251
- exec_ctx, chand->lb_policy,
252
- /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
253
- /* check= */ 0, GRPC_ERROR_REF(error));
241
+ /* TODO: Improve failure handling:
242
+ * - Make it possible for policies to return GRPC_CHANNEL_TRANSIENT_FAILURE.
243
+ * - Hand over pending picks from old policies during the switch that happens
244
+ * when resolver provides an update. */
245
+ if (chand->lb_policy != NULL) {
246
+ if (state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
247
+ /* cancel picks with wait_for_ready=false */
248
+ grpc_lb_policy_cancel_picks_locked(
249
+ exec_ctx, chand->lb_policy,
250
+ /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
251
+ /* check= */ 0, GRPC_ERROR_REF(error));
252
+ } else if (state == GRPC_CHANNEL_SHUTDOWN) {
253
+ /* cancel all picks */
254
+ grpc_lb_policy_cancel_picks_locked(exec_ctx, chand->lb_policy,
255
+ /* mask= */ 0, /* check= */ 0,
256
+ GRPC_ERROR_REF(error));
257
+ }
254
258
  }
255
259
  grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, error,
256
260
  reason);
@@ -353,6 +357,33 @@ static void parse_retry_throttle_params(const grpc_json *field, void *arg) {
353
357
  }
354
358
  }
355
359
 
360
+ // Wrap a closure associated with \a lb_policy. The associated callback (\a
361
+ // wrapped_on_pick_closure_cb) is responsible for unref'ing \a lb_policy after
362
+ // scheduling \a wrapped_closure.
363
+ typedef struct wrapped_on_pick_closure_arg {
364
+ /* the closure instance using this struct as argument */
365
+ grpc_closure wrapper_closure;
366
+
367
+ /* the original closure. Usually a on_complete/notify cb for pick() and ping()
368
+ * calls against the internal RR instance, respectively. */
369
+ grpc_closure *wrapped_closure;
370
+
371
+ /* The policy instance related to the closure */
372
+ grpc_lb_policy *lb_policy;
373
+ } wrapped_on_pick_closure_arg;
374
+
375
+ // Invoke \a arg->wrapped_closure, unref \a arg->lb_policy and free \a arg.
376
+ static void wrapped_on_pick_closure_cb(grpc_exec_ctx *exec_ctx, void *arg,
377
+ grpc_error *error) {
378
+ wrapped_on_pick_closure_arg *wc_arg = arg;
379
+ GPR_ASSERT(wc_arg != NULL);
380
+ GPR_ASSERT(wc_arg->wrapped_closure != NULL);
381
+ GPR_ASSERT(wc_arg->lb_policy != NULL);
382
+ grpc_closure_run(exec_ctx, wc_arg->wrapped_closure, GRPC_ERROR_REF(error));
383
+ GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->lb_policy, "pick_subchannel_wrapping");
384
+ gpr_free(wc_arg);
385
+ }
386
+
356
387
  static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
357
388
  void *arg, grpc_error *error) {
358
389
  channel_data *chand = arg;
@@ -376,26 +407,24 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
376
407
  GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
377
408
  lb_policy_name = channel_arg->value.string;
378
409
  }
379
- // Special case: If all of the addresses are balancer addresses,
380
- // assume that we should use the grpclb policy, regardless of what the
381
- // resolver actually specified.
410
+ // Special case: If at least one balancer address is present, we use
411
+ // the grpclb policy, regardless of what the resolver actually specified.
382
412
  channel_arg =
383
413
  grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
384
414
  if (channel_arg != NULL && channel_arg->type == GRPC_ARG_POINTER) {
385
415
  grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
386
- bool found_backend_address = false;
416
+ bool found_balancer_address = false;
387
417
  for (size_t i = 0; i < addresses->num_addresses; ++i) {
388
- if (!addresses->addresses[i].is_balancer) {
389
- found_backend_address = true;
418
+ if (addresses->addresses[i].is_balancer) {
419
+ found_balancer_address = true;
390
420
  break;
391
421
  }
392
422
  }
393
- if (!found_backend_address) {
423
+ if (found_balancer_address) {
394
424
  if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
395
425
  gpr_log(GPR_INFO,
396
- "resolver requested LB policy %s but provided only balancer "
397
- "addresses, no backend addresses -- forcing use of grpclb LB "
398
- "policy",
426
+ "resolver requested LB policy %s but provided at least one "
427
+ "balancer address -- forcing use of grpclb LB policy",
399
428
  lb_policy_name);
400
429
  }
401
430
  lb_policy_name = "grpclb";
@@ -441,7 +470,7 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
441
470
  grpc_uri_destroy(uri);
442
471
  method_params_table = grpc_service_config_create_method_config_table(
443
472
  exec_ctx, service_config, method_parameters_create_from_json,
444
- &method_parameters_vtable);
473
+ method_parameters_free);
445
474
  grpc_service_config_destroy(service_config);
446
475
  }
447
476
  }
@@ -689,6 +718,8 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
689
718
  if (chand->resolver == NULL) {
690
719
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
691
720
  }
721
+ chand->deadline_checking_enabled =
722
+ grpc_deadline_checking_enabled(args->channel_args);
692
723
  return GRPC_ERROR_NONE;
693
724
  }
694
725
 
@@ -743,12 +774,6 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
743
774
 
744
775
  #define CANCELLED_CALL ((grpc_subchannel_call *)1)
745
776
 
746
- typedef enum {
747
- /* zero so that it can be default-initialized */
748
- GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0,
749
- GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL
750
- } subchannel_creation_phase;
751
-
752
777
  /** Call data. Holds a pointer to grpc_subchannel_call and the
753
778
  associated machinery to create such a pointer.
754
779
  Handles queueing of stream ops until a call object is ready, waiting
@@ -776,8 +801,9 @@ typedef struct client_channel_call_data {
776
801
  gpr_atm subchannel_call;
777
802
  gpr_arena *arena;
778
803
 
779
- subchannel_creation_phase creation_phase;
804
+ bool pick_pending;
780
805
  grpc_connected_subchannel *connected_subchannel;
806
+ grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT];
781
807
  grpc_polling_entity *pollent;
782
808
 
783
809
  grpc_transport_stream_op_batch **waiting_ops;
@@ -878,12 +904,14 @@ static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
878
904
  /* apply service-config level configuration to the call (now that we're
879
905
  * certain it exists) */
880
906
  call_data *calld = elem->call_data;
907
+ channel_data *chand = elem->channel_data;
881
908
  gpr_timespec per_method_deadline;
882
909
  if (set_call_method_params_from_service_config_locked(exec_ctx, elem,
883
910
  &per_method_deadline)) {
884
911
  // If the deadline from the service config is shorter than the one
885
912
  // from the client API, reset the deadline timer.
886
- if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
913
+ if (chand->deadline_checking_enabled &&
914
+ gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
887
915
  calld->deadline = per_method_deadline;
888
916
  grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
889
917
  }
@@ -895,16 +923,18 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
895
923
  grpc_call_element *elem = arg;
896
924
  call_data *calld = elem->call_data;
897
925
  channel_data *chand = elem->channel_data;
898
- GPR_ASSERT(calld->creation_phase ==
899
- GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
926
+ GPR_ASSERT(calld->pick_pending);
927
+ calld->pick_pending = false;
900
928
  grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
901
929
  chand->interested_parties);
902
- calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
903
930
  if (calld->connected_subchannel == NULL) {
904
- gpr_atm_no_barrier_store(&calld->subchannel_call, 1);
931
+ gpr_atm_no_barrier_store(&calld->subchannel_call, (gpr_atm)CANCELLED_CALL);
905
932
  fail_locked(exec_ctx, calld,
906
- GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
907
- "Failed to create subchannel", &error, 1));
933
+ error == GRPC_ERROR_NONE
934
+ ? GRPC_ERROR_CREATE_FROM_STATIC_STRING(
935
+ "Call dropped by load balancing policy")
936
+ : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
937
+ "Failed to create subchannel", &error, 1));
908
938
  } else if (GET_CALL(calld) == CANCELLED_CALL) {
909
939
  /* already cancelled before subchannel became ready */
910
940
  grpc_error *cancellation_error =
@@ -925,7 +955,8 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
925
955
  .path = calld->path,
926
956
  .start_time = calld->call_start_time,
927
957
  .deadline = calld->deadline,
928
- .arena = calld->arena};
958
+ .arena = calld->arena,
959
+ .context = calld->subchannel_call_context};
929
960
  grpc_error *new_error = grpc_connected_subchannel_create_call(
930
961
  exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
931
962
  gpr_atm_rel_store(&calld->subchannel_call,
@@ -954,6 +985,7 @@ typedef struct {
954
985
  grpc_metadata_batch *initial_metadata;
955
986
  uint32_t initial_metadata_flags;
956
987
  grpc_connected_subchannel **connected_subchannel;
988
+ grpc_call_context_element *subchannel_call_context;
957
989
  grpc_closure *on_ready;
958
990
  grpc_call_element *elem;
959
991
  grpc_closure closure;
@@ -965,8 +997,8 @@ typedef struct {
965
997
  static bool pick_subchannel_locked(
966
998
  grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
967
999
  grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
968
- grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
969
- grpc_error *error);
1000
+ grpc_connected_subchannel **connected_subchannel,
1001
+ grpc_call_context_element *subchannel_call_context, grpc_closure *on_ready);
970
1002
 
971
1003
  static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
972
1004
  grpc_error *error) {
@@ -978,49 +1010,49 @@ static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
978
1010
  } else {
979
1011
  if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
980
1012
  cpa->initial_metadata_flags,
981
- cpa->connected_subchannel, cpa->on_ready,
982
- GRPC_ERROR_NONE)) {
1013
+ cpa->connected_subchannel,
1014
+ cpa->subchannel_call_context, cpa->on_ready)) {
983
1015
  grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
984
1016
  }
985
1017
  }
986
1018
  gpr_free(cpa);
987
1019
  }
988
1020
 
1021
+ static void cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
1022
+ grpc_error *error) {
1023
+ channel_data *chand = elem->channel_data;
1024
+ call_data *calld = elem->call_data;
1025
+ if (chand->lb_policy != NULL) {
1026
+ grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
1027
+ &calld->connected_subchannel,
1028
+ GRPC_ERROR_REF(error));
1029
+ }
1030
+ for (grpc_closure *closure = chand->waiting_for_config_closures.head;
1031
+ closure != NULL; closure = closure->next_data.next) {
1032
+ continue_picking_args *cpa = closure->cb_arg;
1033
+ if (cpa->connected_subchannel == &calld->connected_subchannel) {
1034
+ cpa->connected_subchannel = NULL;
1035
+ grpc_closure_sched(exec_ctx, cpa->on_ready,
1036
+ GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1037
+ "Pick cancelled", &error, 1));
1038
+ }
1039
+ }
1040
+ GRPC_ERROR_UNREF(error);
1041
+ }
1042
+
989
1043
  static bool pick_subchannel_locked(
990
1044
  grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
991
1045
  grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
992
- grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
993
- grpc_error *error) {
1046
+ grpc_connected_subchannel **connected_subchannel,
1047
+ grpc_call_context_element *subchannel_call_context,
1048
+ grpc_closure *on_ready) {
994
1049
  GPR_TIMER_BEGIN("pick_subchannel", 0);
995
1050
 
996
1051
  channel_data *chand = elem->channel_data;
997
1052
  call_data *calld = elem->call_data;
998
- continue_picking_args *cpa;
999
- grpc_closure *closure;
1000
1053
 
1001
1054
  GPR_ASSERT(connected_subchannel);
1002
1055
 
1003
- if (initial_metadata == NULL) {
1004
- if (chand->lb_policy != NULL) {
1005
- grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
1006
- connected_subchannel,
1007
- GRPC_ERROR_REF(error));
1008
- }
1009
- for (closure = chand->waiting_for_config_closures.head; closure != NULL;
1010
- closure = closure->next_data.next) {
1011
- cpa = closure->cb_arg;
1012
- if (cpa->connected_subchannel == connected_subchannel) {
1013
- cpa->connected_subchannel = NULL;
1014
- grpc_closure_sched(exec_ctx, cpa->on_ready,
1015
- GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1016
- "Pick cancelled", &error, 1));
1017
- }
1018
- }
1019
- GPR_TIMER_END("pick_subchannel", 0);
1020
- GRPC_ERROR_UNREF(error);
1021
- return true;
1022
- }
1023
- GPR_ASSERT(error == GRPC_ERROR_NONE);
1024
1056
  if (chand->lb_policy != NULL) {
1025
1057
  apply_final_configuration_locked(exec_ctx, elem);
1026
1058
  grpc_lb_policy *lb_policy = chand->lb_policy;
@@ -1043,13 +1075,30 @@ static bool pick_subchannel_locked(
1043
1075
  }
1044
1076
  }
1045
1077
  const grpc_lb_policy_pick_args inputs = {
1046
- initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
1047
- gpr_inf_future(GPR_CLOCK_MONOTONIC)};
1048
- const bool result = grpc_lb_policy_pick_locked(
1049
- exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
1078
+ initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem};
1079
+
1080
+ // Wrap the user-provided callback in order to hold a strong reference to
1081
+ // the LB policy for the duration of the pick.
1082
+ wrapped_on_pick_closure_arg *w_on_pick_arg =
1083
+ gpr_zalloc(sizeof(*w_on_pick_arg));
1084
+ grpc_closure_init(&w_on_pick_arg->wrapper_closure,
1085
+ wrapped_on_pick_closure_cb, w_on_pick_arg,
1086
+ grpc_schedule_on_exec_ctx);
1087
+ w_on_pick_arg->wrapped_closure = on_ready;
1088
+ GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel_wrapping");
1089
+ w_on_pick_arg->lb_policy = lb_policy;
1090
+ const bool pick_done = grpc_lb_policy_pick_locked(
1091
+ exec_ctx, lb_policy, &inputs, connected_subchannel,
1092
+ subchannel_call_context, NULL, &w_on_pick_arg->wrapper_closure);
1093
+ if (pick_done) {
1094
+ /* synchronous grpc_lb_policy_pick call. Unref the LB policy. */
1095
+ GRPC_LB_POLICY_UNREF(exec_ctx, w_on_pick_arg->lb_policy,
1096
+ "pick_subchannel_wrapping");
1097
+ gpr_free(w_on_pick_arg);
1098
+ }
1050
1099
  GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
1051
1100
  GPR_TIMER_END("pick_subchannel", 0);
1052
- return result;
1101
+ return pick_done;
1053
1102
  }
1054
1103
  if (chand->resolver != NULL && !chand->started_resolving) {
1055
1104
  chand->started_resolving = true;
@@ -1059,10 +1108,11 @@ static bool pick_subchannel_locked(
1059
1108
  &chand->on_resolver_result_changed);
1060
1109
  }
1061
1110
  if (chand->resolver != NULL) {
1062
- cpa = gpr_malloc(sizeof(*cpa));
1111
+ continue_picking_args *cpa = gpr_malloc(sizeof(*cpa));
1063
1112
  cpa->initial_metadata = initial_metadata;
1064
1113
  cpa->initial_metadata_flags = initial_metadata_flags;
1065
1114
  cpa->connected_subchannel = connected_subchannel;
1115
+ cpa->subchannel_call_context = subchannel_call_context;
1066
1116
  cpa->on_ready = on_ready;
1067
1117
  cpa->elem = elem;
1068
1118
  grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
@@ -1114,16 +1164,13 @@ static void start_transport_stream_op_batch_locked_inner(
1114
1164
  error to the caller when the first op does get passed down. */
1115
1165
  calld->cancel_error =
1116
1166
  GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error);
1117
- switch (calld->creation_phase) {
1118
- case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
1119
- fail_locked(exec_ctx, calld,
1120
- GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
1121
- break;
1122
- case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
1123
- pick_subchannel_locked(
1124
- exec_ctx, elem, NULL, 0, &calld->connected_subchannel, NULL,
1125
- GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
1126
- break;
1167
+ if (calld->pick_pending) {
1168
+ cancel_pick_locked(
1169
+ exec_ctx, elem,
1170
+ GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
1171
+ } else {
1172
+ fail_locked(exec_ctx, calld,
1173
+ GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error));
1127
1174
  }
1128
1175
  grpc_transport_stream_op_batch_finish_with_failure(
1129
1176
  exec_ctx, op,
@@ -1133,9 +1180,9 @@ static void start_transport_stream_op_batch_locked_inner(
1133
1180
  }
1134
1181
  }
1135
1182
  /* if we don't have a subchannel, try to get one */
1136
- if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1137
- calld->connected_subchannel == NULL && op->send_initial_metadata) {
1138
- calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
1183
+ if (!calld->pick_pending && calld->connected_subchannel == NULL &&
1184
+ op->send_initial_metadata) {
1185
+ calld->pick_pending = true;
1139
1186
  grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
1140
1187
  grpc_combiner_scheduler(chand->combiner, true));
1141
1188
  GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
@@ -1146,24 +1193,34 @@ static void start_transport_stream_op_batch_locked_inner(
1146
1193
  exec_ctx, elem,
1147
1194
  op->payload->send_initial_metadata.send_initial_metadata,
1148
1195
  op->payload->send_initial_metadata.send_initial_metadata_flags,
1149
- &calld->connected_subchannel, &calld->next_step, GRPC_ERROR_NONE)) {
1150
- calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1196
+ &calld->connected_subchannel, calld->subchannel_call_context,
1197
+ &calld->next_step)) {
1198
+ calld->pick_pending = false;
1151
1199
  GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
1200
+ if (calld->connected_subchannel == NULL) {
1201
+ gpr_atm_no_barrier_store(&calld->subchannel_call,
1202
+ (gpr_atm)CANCELLED_CALL);
1203
+ grpc_error *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1204
+ "Call dropped by load balancing policy");
1205
+ fail_locked(exec_ctx, calld, GRPC_ERROR_REF(error));
1206
+ grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error);
1207
+ return; // Early out.
1208
+ }
1152
1209
  } else {
1153
1210
  grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent,
1154
1211
  chand->interested_parties);
1155
1212
  }
1156
1213
  }
1157
1214
  /* if we've got a subchannel, then let's ask it to create a call */
1158
- if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING &&
1159
- calld->connected_subchannel != NULL) {
1215
+ if (!calld->pick_pending && calld->connected_subchannel != NULL) {
1160
1216
  grpc_subchannel_call *subchannel_call = NULL;
1161
1217
  const grpc_connected_subchannel_call_args call_args = {
1162
1218
  .pollent = calld->pollent,
1163
1219
  .path = calld->path,
1164
1220
  .start_time = calld->call_start_time,
1165
1221
  .deadline = calld->deadline,
1166
- .arena = calld->arena};
1222
+ .arena = calld->arena,
1223
+ .context = calld->subchannel_call_context};
1167
1224
  grpc_error *error = grpc_connected_subchannel_create_call(
1168
1225
  exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call);
1169
1226
  gpr_atm_rel_store(&calld->subchannel_call,
@@ -1241,8 +1298,10 @@ static void cc_start_transport_stream_op_batch(
1241
1298
  call_data *calld = elem->call_data;
1242
1299
  channel_data *chand = elem->channel_data;
1243
1300
  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1244
- grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem,
1245
- op);
1301
+ if (chand->deadline_checking_enabled) {
1302
+ grpc_deadline_state_client_start_transport_stream_op_batch(exec_ctx, elem,
1303
+ op);
1304
+ }
1246
1305
  /* try to (atomically) get the call */
1247
1306
  grpc_subchannel_call *call = GET_CALL(calld);
1248
1307
  GPR_TIMER_BEGIN("cc_start_transport_stream_op_batch", 0);
@@ -1276,14 +1335,16 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1276
1335
  grpc_call_element *elem,
1277
1336
  const grpc_call_element_args *args) {
1278
1337
  call_data *calld = elem->call_data;
1338
+ channel_data *chand = elem->channel_data;
1279
1339
  // Initialize data members.
1280
- grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
1281
1340
  calld->path = grpc_slice_ref_internal(args->path);
1282
1341
  calld->call_start_time = args->start_time;
1283
1342
  calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1284
1343
  calld->owning_call = args->call_stack;
1285
1344
  calld->arena = args->arena;
1286
- grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
1345
+ if (chand->deadline_checking_enabled) {
1346
+ grpc_deadline_state_init(exec_ctx, elem, args->call_stack, calld->deadline);
1347
+ }
1287
1348
  return GRPC_ERROR_NONE;
1288
1349
  }
1289
1350
 
@@ -1293,7 +1354,10 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1293
1354
  const grpc_call_final_info *final_info,
1294
1355
  grpc_closure *then_schedule_closure) {
1295
1356
  call_data *calld = elem->call_data;
1296
- grpc_deadline_state_destroy(exec_ctx, elem);
1357
+ channel_data *chand = elem->channel_data;
1358
+ if (chand->deadline_checking_enabled) {
1359
+ grpc_deadline_state_destroy(exec_ctx, elem);
1360
+ }
1297
1361
  grpc_slice_unref_internal(exec_ctx, calld->path);
1298
1362
  if (calld->method_params != NULL) {
1299
1363
  method_parameters_unref(calld->method_params);
@@ -1305,12 +1369,18 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1305
1369
  then_schedule_closure = NULL;
1306
1370
  GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1307
1371
  }
1308
- GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
1372
+ GPR_ASSERT(!calld->pick_pending);
1309
1373
  GPR_ASSERT(calld->waiting_ops_count == 0);
1310
1374
  if (calld->connected_subchannel != NULL) {
1311
1375
  GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
1312
1376
  "picked");
1313
1377
  }
1378
+ for (size_t i = 0; i < GRPC_CONTEXT_COUNT; ++i) {
1379
+ if (calld->subchannel_call_context[i].value != NULL) {
1380
+ calld->subchannel_call_context[i].destroy(
1381
+ calld->subchannel_call_context[i].value);
1382
+ }
1383
+ }
1314
1384
  gpr_free(calld->waiting_ops);
1315
1385
  grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE);
1316
1386
  }
@@ -1490,13 +1560,13 @@ static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1490
1560
 
1491
1561
  void grpc_client_channel_watch_connectivity_state(
1492
1562
  grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset,
1493
- grpc_connectivity_state *state, grpc_closure *on_complete,
1563
+ grpc_connectivity_state *state, grpc_closure *closure,
1494
1564
  grpc_closure *watcher_timer_init) {
1495
1565
  channel_data *chand = elem->channel_data;
1496
1566
  external_connectivity_watcher *w = gpr_zalloc(sizeof(*w));
1497
1567
  w->chand = chand;
1498
1568
  w->pollset = pollset;
1499
- w->on_complete = on_complete;
1569
+ w->on_complete = closure;
1500
1570
  w->state = state;
1501
1571
  w->watcher_timer_init = watcher_timer_init;
1502
1572