grpc 1.1.2 → 1.2.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1257 -404
  3. data/etc/roots.pem +189 -102
  4. data/include/grpc/census.h +7 -7
  5. data/include/grpc/compression.h +4 -4
  6. data/include/grpc/grpc.h +13 -7
  7. data/include/grpc/impl/codegen/atm_gcc_atomic.h +26 -9
  8. data/include/grpc/impl/codegen/grpc_types.h +39 -30
  9. data/include/grpc/impl/codegen/slice.h +24 -6
  10. data/include/grpc/impl/codegen/sync.h +8 -0
  11. data/include/grpc/load_reporting.h +63 -0
  12. data/include/grpc/slice.h +37 -1
  13. data/include/grpc/slice_buffer.h +7 -0
  14. data/include/grpc/support/alloc.h +3 -0
  15. data/include/grpc/support/useful.h +3 -0
  16. data/src/core/ext/census/gen/census.pb.h +1 -1
  17. data/src/core/ext/census/gen/trace_context.pb.c +9 -36
  18. data/src/core/ext/census/gen/trace_context.pb.h +20 -26
  19. data/src/core/ext/census/grpc_filter.c +3 -5
  20. data/src/core/ext/census/trace_context.c +1 -1
  21. data/src/core/ext/census/trace_context.h +3 -0
  22. data/src/core/ext/census/trace_label.h +61 -0
  23. data/src/core/ext/census/trace_propagation.h +63 -0
  24. data/src/core/ext/census/trace_status.h +45 -0
  25. data/src/core/ext/census/trace_string.h +50 -0
  26. data/src/core/ext/census/tracing.c +31 -11
  27. data/src/core/ext/census/tracing.h +124 -0
  28. data/src/core/ext/client_channel/client_channel.c +456 -368
  29. data/src/core/ext/client_channel/client_channel.h +4 -0
  30. data/src/core/ext/client_channel/client_channel_plugin.c +6 -1
  31. data/src/core/ext/client_channel/connector.c +3 -3
  32. data/src/core/ext/client_channel/connector.h +4 -3
  33. data/src/core/ext/client_channel/http_connect_handshaker.c +62 -72
  34. data/src/core/ext/client_channel/http_connect_handshaker.h +7 -10
  35. data/src/core/ext/client_channel/http_proxy.c +125 -0
  36. data/src/core/ext/client_channel/http_proxy.h +39 -0
  37. data/src/core/ext/client_channel/lb_policy.c +56 -35
  38. data/src/core/ext/client_channel/lb_policy.h +46 -39
  39. data/src/core/ext/client_channel/lb_policy_factory.h +1 -0
  40. data/src/core/ext/client_channel/parse_address.c +32 -6
  41. data/src/core/ext/client_channel/proxy_mapper.c +63 -0
  42. data/src/core/ext/client_channel/proxy_mapper.h +89 -0
  43. data/src/core/ext/client_channel/proxy_mapper_registry.c +133 -0
  44. data/src/core/ext/client_channel/proxy_mapper_registry.h +59 -0
  45. data/src/core/ext/client_channel/resolver.c +16 -9
  46. data/src/core/ext/client_channel/resolver.h +23 -12
  47. data/src/core/ext/client_channel/resolver_factory.h +1 -0
  48. data/src/core/ext/client_channel/resolver_registry.c +15 -11
  49. data/src/core/ext/client_channel/resolver_registry.h +5 -3
  50. data/src/core/ext/client_channel/subchannel.c +44 -27
  51. data/src/core/ext/client_channel/subchannel.h +6 -2
  52. data/src/core/ext/client_channel/uri_parser.c +26 -14
  53. data/src/core/ext/client_channel/uri_parser.h +3 -1
  54. data/src/core/ext/lb_policy/grpclb/grpclb.c +220 -209
  55. data/src/core/ext/lb_policy/grpclb/grpclb_channel.h +56 -0
  56. data/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c +107 -0
  57. data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +3 -6
  58. data/src/core/ext/lb_policy/pick_first/pick_first.c +71 -116
  59. data/src/core/ext/lb_policy/round_robin/round_robin.c +52 -67
  60. data/src/core/ext/load_reporting/load_reporting.c +20 -0
  61. data/src/core/ext/load_reporting/load_reporting.h +1 -16
  62. data/src/core/ext/load_reporting/load_reporting_filter.c +28 -54
  63. data/src/core/ext/resolver/dns/native/dns_resolver.c +31 -45
  64. data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +20 -29
  65. data/src/core/ext/transport/chttp2/client/chttp2_connector.c +11 -8
  66. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +11 -2
  67. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +143 -46
  68. data/src/core/ext/transport/chttp2/server/chttp2_server.c +12 -50
  69. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +1 -1
  70. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +1 -1
  71. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +7 -7
  72. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +1 -2
  73. data/src/core/ext/transport/chttp2/transport/bin_encoder.h +1 -2
  74. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +0 -3
  75. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +606 -374
  76. data/src/core/ext/transport/chttp2/transport/frame_ping.c +17 -5
  77. data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -2
  78. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +9 -13
  79. data/src/core/ext/transport/chttp2/transport/frame_settings.c +12 -11
  80. data/src/core/ext/transport/chttp2/transport/frame_settings.h +1 -1
  81. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +5 -6
  82. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +100 -53
  83. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -2
  84. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +126 -70
  85. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +13 -7
  86. data/src/core/ext/transport/chttp2/transport/hpack_table.c +22 -19
  87. data/src/core/ext/transport/chttp2/transport/hpack_table.h +6 -6
  88. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +23 -11
  89. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +6 -2
  90. data/src/core/ext/transport/chttp2/transport/internal.h +169 -42
  91. data/src/core/ext/transport/chttp2/transport/parsing.c +98 -41
  92. data/src/core/ext/transport/chttp2/transport/stream_lists.c +29 -14
  93. data/src/core/ext/transport/chttp2/transport/writing.c +137 -15
  94. data/src/core/lib/channel/channel_stack.c +14 -44
  95. data/src/core/lib/channel/channel_stack.h +10 -17
  96. data/src/core/lib/channel/channel_stack_builder.c +2 -3
  97. data/src/core/lib/channel/compress_filter.c +54 -46
  98. data/src/core/lib/channel/connected_channel.c +4 -4
  99. data/src/core/lib/channel/connected_channel.h +5 -0
  100. data/src/core/lib/channel/context.h +3 -0
  101. data/src/core/lib/channel/deadline_filter.c +61 -61
  102. data/src/core/lib/channel/deadline_filter.h +8 -5
  103. data/src/core/lib/channel/handshaker.c +47 -7
  104. data/src/core/lib/channel/handshaker.h +21 -3
  105. data/src/core/lib/channel/http_client_filter.c +149 -99
  106. data/src/core/lib/channel/http_server_filter.c +163 -147
  107. data/src/core/lib/channel/message_size_filter.c +15 -10
  108. data/src/core/lib/compression/algorithm_metadata.h +4 -4
  109. data/src/core/lib/compression/compression.c +17 -23
  110. data/src/core/lib/http/httpcli.c +3 -2
  111. data/src/core/lib/http/httpcli.h +2 -1
  112. data/src/core/lib/http/httpcli_security_connector.c +2 -3
  113. data/src/core/lib/http/parser.c +2 -2
  114. data/src/core/lib/iomgr/closure.c +6 -3
  115. data/src/core/lib/iomgr/closure.h +4 -2
  116. data/src/core/lib/iomgr/combiner.c +35 -5
  117. data/src/core/lib/iomgr/combiner.h +21 -2
  118. data/src/core/lib/iomgr/endpoint.c +3 -2
  119. data/src/core/lib/iomgr/endpoint.h +3 -2
  120. data/src/core/lib/iomgr/error.c +60 -94
  121. data/src/core/lib/iomgr/error.h +7 -10
  122. data/src/core/lib/iomgr/error_internal.h +54 -0
  123. data/src/core/lib/iomgr/ev_epoll_linux.c +253 -109
  124. data/src/core/lib/iomgr/ev_poll_posix.c +61 -29
  125. data/src/core/lib/iomgr/ev_posix.c +7 -8
  126. data/src/core/lib/iomgr/ev_posix.h +4 -4
  127. data/src/core/lib/iomgr/exec_ctx.c +11 -6
  128. data/src/core/lib/iomgr/exec_ctx.h +11 -14
  129. data/src/core/lib/iomgr/executor.c +2 -2
  130. data/src/core/lib/iomgr/load_file.c +1 -1
  131. data/src/core/lib/iomgr/network_status_tracker.c +5 -81
  132. data/src/core/lib/iomgr/pollset.h +1 -3
  133. data/src/core/lib/iomgr/pollset_set.h +2 -1
  134. data/src/core/lib/iomgr/pollset_set_uv.c +2 -1
  135. data/src/core/lib/iomgr/pollset_set_windows.c +2 -1
  136. data/src/core/lib/iomgr/pollset_uv.c +25 -11
  137. data/src/core/lib/iomgr/pollset_windows.c +0 -11
  138. data/src/core/lib/iomgr/resolve_address_uv.c +50 -2
  139. data/src/core/lib/iomgr/resource_quota.c +41 -11
  140. data/src/core/lib/iomgr/resource_quota.h +6 -0
  141. data/src/core/lib/iomgr/sockaddr_utils.c +33 -17
  142. data/src/core/lib/iomgr/sockaddr_utils.h +4 -0
  143. data/src/core/lib/iomgr/tcp_client_posix.c +2 -3
  144. data/src/core/lib/iomgr/tcp_client_uv.c +1 -3
  145. data/src/core/lib/iomgr/tcp_client_windows.c +21 -6
  146. data/src/core/lib/iomgr/tcp_posix.c +4 -5
  147. data/src/core/lib/iomgr/tcp_server_posix.c +269 -94
  148. data/src/core/lib/iomgr/tcp_server_windows.c +1 -1
  149. data/src/core/lib/iomgr/tcp_uv.c +11 -5
  150. data/src/core/lib/iomgr/tcp_windows.c +20 -7
  151. data/src/core/lib/iomgr/timer_generic.c +15 -22
  152. data/src/core/lib/iomgr/timer_generic.h +1 -1
  153. data/src/core/lib/iomgr/timer_uv.c +10 -6
  154. data/src/core/lib/iomgr/timer_uv.h +1 -1
  155. data/src/core/lib/iomgr/udp_server.c +45 -6
  156. data/src/core/lib/iomgr/udp_server.h +7 -1
  157. data/src/core/lib/iomgr/unix_sockets_posix.c +11 -1
  158. data/src/core/lib/json/json.c +1 -2
  159. data/src/core/lib/profiling/basic_timers.c +17 -3
  160. data/src/core/lib/security/context/security_context.c +3 -10
  161. data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -8
  162. data/src/core/lib/security/credentials/credentials.c +48 -2
  163. data/src/core/lib/security/credentials/credentials.h +13 -0
  164. data/src/core/lib/security/credentials/credentials_metadata.c +1 -2
  165. data/src/core/lib/security/credentials/fake/fake_credentials.c +6 -8
  166. data/src/core/lib/security/credentials/fake/fake_credentials.h +15 -0
  167. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +3 -3
  168. data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -2
  169. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -2
  170. data/src/core/lib/security/credentials/jwt/jwt_verifier.c +5 -8
  171. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
  172. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +3 -5
  173. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +15 -13
  174. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +2 -4
  175. data/src/core/lib/security/transport/client_auth_filter.c +72 -47
  176. data/src/core/lib/security/transport/lb_targets_info.c +70 -0
  177. data/src/core/lib/security/transport/lb_targets_info.h +47 -0
  178. data/src/core/lib/security/transport/secure_endpoint.c +3 -3
  179. data/src/core/lib/security/transport/security_connector.c +125 -28
  180. data/src/core/lib/security/transport/security_connector.h +4 -3
  181. data/src/core/lib/security/transport/security_handshaker.c +13 -9
  182. data/src/core/lib/security/transport/server_auth_filter.c +31 -40
  183. data/src/core/lib/security/util/b64.c +1 -1
  184. data/src/core/lib/slice/slice.c +110 -20
  185. data/src/core/lib/slice/slice_buffer.c +92 -39
  186. data/src/core/lib/{transport/mdstr_hash_table.c → slice/slice_hash_table.c} +40 -33
  187. data/src/core/lib/{transport/mdstr_hash_table.h → slice/slice_hash_table.h} +21 -21
  188. data/src/core/lib/slice/slice_intern.c +346 -0
  189. data/src/core/lib/slice/slice_internal.h +15 -0
  190. data/src/core/lib/slice/slice_string_helpers.c +5 -0
  191. data/src/core/lib/slice/slice_string_helpers.h +5 -0
  192. data/src/core/lib/support/alloc.c +26 -1
  193. data/src/core/lib/support/cmdline.c +2 -4
  194. data/src/core/lib/support/cpu_posix.c +2 -7
  195. data/src/core/lib/support/histogram.c +1 -2
  196. data/src/core/lib/support/log_posix.c +8 -4
  197. data/src/core/lib/support/spinlock.h +52 -0
  198. data/src/core/lib/support/subprocess_posix.c +1 -2
  199. data/src/core/lib/support/sync.c +7 -1
  200. data/src/core/lib/support/sync_posix.c +9 -0
  201. data/src/core/lib/support/time_windows.c +7 -1
  202. data/src/core/lib/surface/call.c +647 -629
  203. data/src/core/lib/surface/call.h +4 -1
  204. data/src/core/lib/surface/call_details.c +8 -2
  205. data/src/core/lib/surface/call_log_batch.c +17 -6
  206. data/src/core/lib/surface/channel.c +49 -59
  207. data/src/core/lib/surface/channel.h +5 -6
  208. data/src/core/lib/surface/completion_queue.c +16 -45
  209. data/src/core/lib/surface/completion_queue.h +0 -3
  210. data/src/core/lib/surface/init.c +6 -2
  211. data/src/core/lib/surface/init_secure.c +1 -1
  212. data/src/core/lib/surface/lame_client.c +14 -4
  213. data/src/core/lib/surface/server.c +79 -82
  214. data/src/core/lib/surface/validate_metadata.c +46 -15
  215. data/src/core/lib/surface/validate_metadata.h +43 -0
  216. data/src/core/lib/surface/version.c +2 -2
  217. data/src/core/lib/transport/bdp_estimator.c +104 -0
  218. data/src/core/lib/transport/bdp_estimator.h +76 -0
  219. data/src/core/lib/transport/connectivity_state.c +33 -13
  220. data/src/core/lib/transport/connectivity_state.h +15 -5
  221. data/src/core/lib/transport/error_utils.c +124 -0
  222. data/src/core/lib/transport/error_utils.h +56 -0
  223. data/src/core/{ext/transport/chttp2 → lib}/transport/http2_errors.h +18 -18
  224. data/src/core/lib/transport/metadata.c +259 -503
  225. data/src/core/lib/transport/metadata.h +69 -68
  226. data/src/core/lib/transport/metadata_batch.c +183 -63
  227. data/src/core/lib/transport/metadata_batch.h +50 -26
  228. data/src/core/lib/transport/pid_controller.c +28 -8
  229. data/src/core/lib/transport/pid_controller.h +15 -2
  230. data/src/core/lib/transport/service_config.c +21 -18
  231. data/src/core/lib/transport/service_config.h +5 -5
  232. data/src/core/lib/transport/static_metadata.c +753 -112
  233. data/src/core/lib/transport/static_metadata.h +403 -264
  234. data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.c +18 -20
  235. data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.h +9 -10
  236. data/src/core/lib/transport/timeout_encoding.c +11 -9
  237. data/src/core/lib/transport/timeout_encoding.h +3 -1
  238. data/src/core/lib/transport/transport.c +47 -87
  239. data/src/core/lib/transport/transport.h +20 -25
  240. data/src/core/lib/transport/transport_op_string.c +7 -19
  241. data/src/core/lib/tsi/fake_transport_security.c +2 -4
  242. data/src/core/lib/tsi/ssl_transport_security.c +7 -16
  243. data/src/core/lib/tsi/transport_security.c +2 -4
  244. data/src/ruby/ext/grpc/extconf.rb +4 -1
  245. data/src/ruby/ext/grpc/rb_byte_buffer.c +7 -0
  246. data/src/ruby/ext/grpc/rb_byte_buffer.h +3 -0
  247. data/src/ruby/ext/grpc/rb_call.c +47 -46
  248. data/src/ruby/ext/grpc/rb_channel.c +21 -6
  249. data/src/ruby/ext/grpc/rb_compression_options.c +9 -6
  250. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +36 -2
  251. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +59 -8
  252. data/src/ruby/ext/grpc/rb_server.c +6 -4
  253. data/src/ruby/lib/grpc/generic/client_stub.rb +1 -1
  254. data/src/ruby/lib/grpc/version.rb +1 -1
  255. metadata +33 -9
@@ -43,15 +43,19 @@
43
43
  #include <grpc/support/sync.h>
44
44
  #include <grpc/support/useful.h>
45
45
 
46
+ #include "src/core/ext/client_channel/http_connect_handshaker.h"
46
47
  #include "src/core/ext/client_channel/lb_policy_registry.h"
48
+ #include "src/core/ext/client_channel/proxy_mapper_registry.h"
47
49
  #include "src/core/ext/client_channel/resolver_registry.h"
48
50
  #include "src/core/ext/client_channel/subchannel.h"
49
51
  #include "src/core/lib/channel/channel_args.h"
50
52
  #include "src/core/lib/channel/connected_channel.h"
51
53
  #include "src/core/lib/channel/deadline_filter.h"
54
+ #include "src/core/lib/iomgr/combiner.h"
52
55
  #include "src/core/lib/iomgr/iomgr.h"
53
56
  #include "src/core/lib/iomgr/polling_entity.h"
54
57
  #include "src/core/lib/profiling/timers.h"
58
+ #include "src/core/lib/slice/slice_internal.h"
55
59
  #include "src/core/lib/support/string.h"
56
60
  #include "src/core/lib/surface/channel.h"
57
61
  #include "src/core/lib/transport/connectivity_state.h"
@@ -72,24 +76,82 @@ typedef enum {
72
76
  WAIT_FOR_READY_TRUE
73
77
  } wait_for_ready_value;
74
78
 
75
- typedef struct method_parameters {
79
+ typedef struct {
80
+ gpr_refcount refs;
76
81
  gpr_timespec timeout;
77
82
  wait_for_ready_value wait_for_ready;
78
83
  } method_parameters;
79
84
 
85
+ static method_parameters *method_parameters_ref(
86
+ method_parameters *method_params) {
87
+ gpr_ref(&method_params->refs);
88
+ return method_params;
89
+ }
90
+
91
+ static void method_parameters_unref(method_parameters *method_params) {
92
+ if (gpr_unref(&method_params->refs)) {
93
+ gpr_free(method_params);
94
+ }
95
+ }
96
+
80
97
  static void *method_parameters_copy(void *value) {
81
- void *new_value = gpr_malloc(sizeof(method_parameters));
82
- memcpy(new_value, value, sizeof(method_parameters));
83
- return new_value;
98
+ return method_parameters_ref(value);
84
99
  }
85
100
 
86
- static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *p) {
87
- gpr_free(p);
101
+ static void method_parameters_free(grpc_exec_ctx *exec_ctx, void *value) {
102
+ method_parameters_unref(value);
88
103
  }
89
104
 
90
- static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
105
+ static const grpc_slice_hash_table_vtable method_parameters_vtable = {
91
106
  method_parameters_free, method_parameters_copy};
92
107
 
108
+ static bool parse_wait_for_ready(grpc_json *field,
109
+ wait_for_ready_value *wait_for_ready) {
110
+ if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
111
+ return false;
112
+ }
113
+ *wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
114
+ : WAIT_FOR_READY_FALSE;
115
+ return true;
116
+ }
117
+
118
+ static bool parse_timeout(grpc_json *field, gpr_timespec *timeout) {
119
+ if (field->type != GRPC_JSON_STRING) return false;
120
+ size_t len = strlen(field->value);
121
+ if (field->value[len - 1] != 's') return false;
122
+ char *buf = gpr_strdup(field->value);
123
+ buf[len - 1] = '\0'; // Remove trailing 's'.
124
+ char *decimal_point = strchr(buf, '.');
125
+ if (decimal_point != NULL) {
126
+ *decimal_point = '\0';
127
+ timeout->tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
128
+ if (timeout->tv_nsec == -1) {
129
+ gpr_free(buf);
130
+ return false;
131
+ }
132
+ // There should always be exactly 3, 6, or 9 fractional digits.
133
+ int multiplier = 1;
134
+ switch (strlen(decimal_point + 1)) {
135
+ case 9:
136
+ break;
137
+ case 6:
138
+ multiplier *= 1000;
139
+ break;
140
+ case 3:
141
+ multiplier *= 1000000;
142
+ break;
143
+ default: // Unsupported number of digits.
144
+ gpr_free(buf);
145
+ return false;
146
+ }
147
+ timeout->tv_nsec *= multiplier;
148
+ }
149
+ timeout->tv_sec = gpr_parse_nonnegative_int(buf);
150
+ gpr_free(buf);
151
+ if (timeout->tv_sec == -1) return false;
152
+ return true;
153
+ }
154
+
93
155
  static void *method_parameters_create_from_json(const grpc_json *json) {
94
156
  wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
95
157
  gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
@@ -97,49 +159,14 @@ static void *method_parameters_create_from_json(const grpc_json *json) {
97
159
  if (field->key == NULL) continue;
98
160
  if (strcmp(field->key, "waitForReady") == 0) {
99
161
  if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
100
- if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
101
- return NULL;
102
- }
103
- wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
104
- : WAIT_FOR_READY_FALSE;
162
+ if (!parse_wait_for_ready(field, &wait_for_ready)) return NULL;
105
163
  } else if (strcmp(field->key, "timeout") == 0) {
106
164
  if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
107
- if (field->type != GRPC_JSON_STRING) return NULL;
108
- size_t len = strlen(field->value);
109
- if (field->value[len - 1] != 's') return NULL;
110
- char *buf = gpr_strdup(field->value);
111
- buf[len - 1] = '\0'; // Remove trailing 's'.
112
- char *decimal_point = strchr(buf, '.');
113
- if (decimal_point != NULL) {
114
- *decimal_point = '\0';
115
- timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
116
- if (timeout.tv_nsec == -1) {
117
- gpr_free(buf);
118
- return NULL;
119
- }
120
- // There should always be exactly 3, 6, or 9 fractional digits.
121
- int multiplier = 1;
122
- switch (strlen(decimal_point + 1)) {
123
- case 9:
124
- break;
125
- case 6:
126
- multiplier *= 1000;
127
- break;
128
- case 3:
129
- multiplier *= 1000000;
130
- break;
131
- default: // Unsupported number of digits.
132
- gpr_free(buf);
133
- return NULL;
134
- }
135
- timeout.tv_nsec *= multiplier;
136
- }
137
- timeout.tv_sec = gpr_parse_nonnegative_int(buf);
138
- if (timeout.tv_sec == -1) return NULL;
139
- gpr_free(buf);
165
+ if (!parse_timeout(field, &timeout)) return NULL;
140
166
  }
141
167
  }
142
168
  method_parameters *value = gpr_malloc(sizeof(method_parameters));
169
+ gpr_ref_init(&value->refs, 1);
143
170
  value->timeout = timeout;
144
171
  value->wait_for_ready = wait_for_ready;
145
172
  return value;
@@ -157,15 +184,12 @@ typedef struct client_channel_channel_data {
157
184
  /** client channel factory */
158
185
  grpc_client_channel_factory *client_channel_factory;
159
186
 
160
- /** mutex protecting all variables below in this data structure */
161
- gpr_mu mu;
187
+ /** combiner protecting all variables below in this data structure */
188
+ grpc_combiner *combiner;
162
189
  /** currently active load balancer */
163
- char *lb_policy_name;
164
190
  grpc_lb_policy *lb_policy;
165
- /** service config in JSON form */
166
- char *service_config_json;
167
191
  /** maps method names to method_parameters structs */
168
- grpc_mdstr_hash_table *method_params_table;
192
+ grpc_slice_hash_table *method_params_table;
169
193
  /** incoming resolver result - set by resolver.next() */
170
194
  grpc_channel_args *resolver_result;
171
195
  /** a list of closures that are all waiting for config to come in */
@@ -180,6 +204,13 @@ typedef struct client_channel_channel_data {
180
204
  grpc_channel_stack *owning_stack;
181
205
  /** interested parties (owned) */
182
206
  grpc_pollset_set *interested_parties;
207
+
208
+ /* the following properties are guarded by a mutex since API's require them
209
+ to be instantaneously available */
210
+ gpr_mu info_mu;
211
+ char *info_lb_policy_name;
212
+ /** service config in JSON form */
213
+ char *info_service_config_json;
183
214
  } channel_data;
184
215
 
185
216
  /** We create one watcher for each new lb_policy that is returned from a
@@ -192,9 +223,9 @@ typedef struct {
192
223
  grpc_lb_policy *lb_policy;
193
224
  } lb_policy_connectivity_watcher;
194
225
 
195
- static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
196
- grpc_lb_policy *lb_policy,
197
- grpc_connectivity_state current_state);
226
+ static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
227
+ grpc_lb_policy *lb_policy,
228
+ grpc_connectivity_state current_state);
198
229
 
199
230
  static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
200
231
  channel_data *chand,
@@ -205,7 +236,7 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
205
236
  state == GRPC_CHANNEL_SHUTDOWN) &&
206
237
  chand->lb_policy != NULL) {
207
238
  /* cancel picks with wait_for_ready=false */
208
- grpc_lb_policy_cancel_picks(
239
+ grpc_lb_policy_cancel_picks_locked(
209
240
  exec_ctx, chand->lb_policy,
210
241
  /* mask= */ GRPC_INITIAL_METADATA_WAIT_FOR_READY,
211
242
  /* check= */ 0, GRPC_ERROR_REF(error));
@@ -215,59 +246,50 @@ static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
215
246
  }
216
247
 
217
248
  static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
218
- lb_policy_connectivity_watcher *w,
219
- grpc_error *error) {
249
+ void *arg, grpc_error *error) {
250
+ lb_policy_connectivity_watcher *w = arg;
220
251
  grpc_connectivity_state publish_state = w->state;
221
- /* check if the notification is for a stale policy */
222
- if (w->lb_policy != w->chand->lb_policy) return;
223
-
224
- if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
225
- publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
226
- grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver);
227
- GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
228
- w->chand->lb_policy = NULL;
229
- }
230
- set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
231
- GRPC_ERROR_REF(error), "lb_changed");
232
- if (w->state != GRPC_CHANNEL_SHUTDOWN) {
233
- watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
252
+ /* check if the notification is for the latest policy */
253
+ if (w->lb_policy == w->chand->lb_policy) {
254
+ if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
255
+ publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
256
+ grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
257
+ GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
258
+ w->chand->lb_policy = NULL;
259
+ }
260
+ set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
261
+ GRPC_ERROR_REF(error), "lb_changed");
262
+ if (w->state != GRPC_CHANNEL_SHUTDOWN) {
263
+ watch_lb_policy_locked(exec_ctx, w->chand, w->lb_policy, w->state);
264
+ }
234
265
  }
235
- }
236
-
237
- static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
238
- grpc_error *error) {
239
- lb_policy_connectivity_watcher *w = arg;
240
-
241
- gpr_mu_lock(&w->chand->mu);
242
- on_lb_policy_state_changed_locked(exec_ctx, w, error);
243
- gpr_mu_unlock(&w->chand->mu);
244
266
 
245
267
  GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack, "watch_lb_policy");
246
268
  gpr_free(w);
247
269
  }
248
270
 
249
- static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
250
- grpc_lb_policy *lb_policy,
251
- grpc_connectivity_state current_state) {
271
+ static void watch_lb_policy_locked(grpc_exec_ctx *exec_ctx, channel_data *chand,
272
+ grpc_lb_policy *lb_policy,
273
+ grpc_connectivity_state current_state) {
252
274
  lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
253
275
  GRPC_CHANNEL_STACK_REF(chand->owning_stack, "watch_lb_policy");
254
276
 
255
277
  w->chand = chand;
256
- grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w,
257
- grpc_schedule_on_exec_ctx);
278
+ grpc_closure_init(&w->on_changed, on_lb_policy_state_changed_locked, w,
279
+ grpc_combiner_scheduler(chand->combiner, false));
258
280
  w->state = current_state;
259
281
  w->lb_policy = lb_policy;
260
- grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
261
- &w->on_changed);
282
+ grpc_lb_policy_notify_on_state_change_locked(exec_ctx, lb_policy, &w->state,
283
+ &w->on_changed);
262
284
  }
263
285
 
264
- static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
265
- grpc_error *error) {
286
+ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
287
+ void *arg, grpc_error *error) {
266
288
  channel_data *chand = arg;
267
289
  char *lb_policy_name = NULL;
268
290
  grpc_lb_policy *lb_policy = NULL;
269
291
  grpc_lb_policy *old_lb_policy;
270
- grpc_mdstr_hash_table *method_params_table = NULL;
292
+ grpc_slice_hash_table *method_params_table = NULL;
271
293
  grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
272
294
  bool exit_idle = false;
273
295
  grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
@@ -314,13 +336,14 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
314
336
  grpc_lb_policy_args lb_policy_args;
315
337
  lb_policy_args.args = chand->resolver_result;
316
338
  lb_policy_args.client_channel_factory = chand->client_channel_factory;
339
+ lb_policy_args.combiner = chand->combiner;
317
340
  lb_policy =
318
341
  grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
319
342
  if (lb_policy != NULL) {
320
343
  GRPC_LB_POLICY_REF(lb_policy, "config_change");
321
344
  GRPC_ERROR_UNREF(state_error);
322
- state =
323
- grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
345
+ state = grpc_lb_policy_check_connectivity_locked(exec_ctx, lb_policy,
346
+ &state_error);
324
347
  }
325
348
  // Find service config.
326
349
  channel_arg =
@@ -350,19 +373,20 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
350
373
  chand->interested_parties);
351
374
  }
352
375
 
353
- gpr_mu_lock(&chand->mu);
376
+ gpr_mu_lock(&chand->info_mu);
354
377
  if (lb_policy_name != NULL) {
355
- gpr_free(chand->lb_policy_name);
356
- chand->lb_policy_name = lb_policy_name;
378
+ gpr_free(chand->info_lb_policy_name);
379
+ chand->info_lb_policy_name = lb_policy_name;
357
380
  }
358
381
  old_lb_policy = chand->lb_policy;
359
382
  chand->lb_policy = lb_policy;
360
383
  if (service_config_json != NULL) {
361
- gpr_free(chand->service_config_json);
362
- chand->service_config_json = service_config_json;
384
+ gpr_free(chand->info_service_config_json);
385
+ chand->info_service_config_json = service_config_json;
363
386
  }
387
+ gpr_mu_unlock(&chand->info_mu);
364
388
  if (chand->method_params_table != NULL) {
365
- grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
389
+ grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
366
390
  }
367
391
  chand->method_params_table = method_params_table;
368
392
  if (lb_policy != NULL) {
@@ -383,15 +407,15 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
383
407
  set_channel_connectivity_state_locked(
384
408
  exec_ctx, chand, state, GRPC_ERROR_REF(state_error), "new_lb+resolver");
385
409
  if (lb_policy != NULL) {
386
- watch_lb_policy(exec_ctx, chand, lb_policy, state);
410
+ watch_lb_policy_locked(exec_ctx, chand, lb_policy, state);
387
411
  }
388
412
  GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
389
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
390
- &chand->on_resolver_result_changed);
391
- gpr_mu_unlock(&chand->mu);
413
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
414
+ &chand->resolver_result,
415
+ &chand->on_resolver_result_changed);
392
416
  } else {
393
417
  if (chand->resolver != NULL) {
394
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
418
+ grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
395
419
  GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
396
420
  chand->resolver = NULL;
397
421
  }
@@ -401,11 +425,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
401
425
  GRPC_ERROR_CREATE_REFERENCING("Got config after disconnection", refs,
402
426
  GPR_ARRAY_SIZE(refs)),
403
427
  "resolver_gone");
404
- gpr_mu_unlock(&chand->mu);
405
428
  }
406
429
 
407
430
  if (exit_idle) {
408
- grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
431
+ grpc_lb_policy_exit_idle_locked(exec_ctx, lb_policy);
409
432
  GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
410
433
  }
411
434
 
@@ -423,20 +446,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
423
446
  GRPC_ERROR_UNREF(state_error);
424
447
  }
425
448
 
426
- static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
427
- grpc_channel_element *elem,
428
- grpc_transport_op *op) {
449
+ static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
450
+ grpc_error *error_ignored) {
451
+ grpc_transport_op *op = arg;
452
+ grpc_channel_element *elem = op->transport_private.args[0];
429
453
  channel_data *chand = elem->channel_data;
430
454
 
431
- grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
432
-
433
- GPR_ASSERT(op->set_accept_stream == false);
434
- if (op->bind_pollset != NULL) {
435
- grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
436
- op->bind_pollset);
437
- }
438
-
439
- gpr_mu_lock(&chand->mu);
440
455
  if (op->on_connectivity_state_change != NULL) {
441
456
  grpc_connectivity_state_notify_on_state_change(
442
457
  exec_ctx, &chand->state_tracker, op->connectivity_state,
@@ -450,7 +465,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
450
465
  grpc_closure_sched(exec_ctx, op->send_ping,
451
466
  GRPC_ERROR_CREATE("Ping with no load balancing"));
452
467
  } else {
453
- grpc_lb_policy_ping_one(exec_ctx, chand->lb_policy, op->send_ping);
468
+ grpc_lb_policy_ping_one_locked(exec_ctx, chand->lb_policy, op->send_ping);
454
469
  op->bind_pollset = NULL;
455
470
  }
456
471
  op->send_ping = NULL;
@@ -461,7 +476,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
461
476
  set_channel_connectivity_state_locked(
462
477
  exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
463
478
  GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
464
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
479
+ grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
465
480
  GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
466
481
  chand->resolver = NULL;
467
482
  if (!chand->started_resolving) {
@@ -479,25 +494,48 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
479
494
  }
480
495
  GRPC_ERROR_UNREF(op->disconnect_with_error);
481
496
  }
482
- gpr_mu_unlock(&chand->mu);
497
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "start_transport_op");
498
+
499
+ grpc_closure_sched(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
500
+ }
501
+
502
+ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
503
+ grpc_channel_element *elem,
504
+ grpc_transport_op *op) {
505
+ channel_data *chand = elem->channel_data;
506
+
507
+ GPR_ASSERT(op->set_accept_stream == false);
508
+ if (op->bind_pollset != NULL) {
509
+ grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
510
+ op->bind_pollset);
511
+ }
512
+
513
+ op->transport_private.args[0] = elem;
514
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack, "start_transport_op");
515
+ grpc_closure_sched(
516
+ exec_ctx, grpc_closure_init(
517
+ &op->transport_private.closure, start_transport_op_locked,
518
+ op, grpc_combiner_scheduler(chand->combiner, false)),
519
+ GRPC_ERROR_NONE);
483
520
  }
484
521
 
485
522
  static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
486
523
  grpc_channel_element *elem,
487
524
  const grpc_channel_info *info) {
488
525
  channel_data *chand = elem->channel_data;
489
- gpr_mu_lock(&chand->mu);
526
+ gpr_mu_lock(&chand->info_mu);
490
527
  if (info->lb_policy_name != NULL) {
491
- *info->lb_policy_name = chand->lb_policy_name == NULL
528
+ *info->lb_policy_name = chand->info_lb_policy_name == NULL
492
529
  ? NULL
493
- : gpr_strdup(chand->lb_policy_name);
530
+ : gpr_strdup(chand->info_lb_policy_name);
494
531
  }
495
532
  if (info->service_config_json != NULL) {
496
- *info->service_config_json = chand->service_config_json == NULL
497
- ? NULL
498
- : gpr_strdup(chand->service_config_json);
533
+ *info->service_config_json =
534
+ chand->info_service_config_json == NULL
535
+ ? NULL
536
+ : gpr_strdup(chand->info_service_config_json);
499
537
  }
500
- gpr_mu_unlock(&chand->mu);
538
+ gpr_mu_unlock(&chand->info_mu);
501
539
  }
502
540
 
503
541
  /* Constructor for channel_data */
@@ -505,15 +543,15 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
505
543
  grpc_channel_element *elem,
506
544
  grpc_channel_element_args *args) {
507
545
  channel_data *chand = elem->channel_data;
508
- memset(chand, 0, sizeof(*chand));
509
546
  GPR_ASSERT(args->is_last);
510
547
  GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
511
548
  // Initialize data members.
512
- gpr_mu_init(&chand->mu);
549
+ chand->combiner = grpc_combiner_create(NULL);
550
+ gpr_mu_init(&chand->info_mu);
513
551
  chand->owning_stack = args->channel_stack;
514
552
  grpc_closure_init(&chand->on_resolver_result_changed,
515
- on_resolver_result_changed, chand,
516
- grpc_schedule_on_exec_ctx);
553
+ on_resolver_result_changed_locked, chand,
554
+ grpc_combiner_scheduler(chand->combiner, false));
517
555
  chand->interested_parties = grpc_pollset_set_create();
518
556
  grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
519
557
  "client_channel");
@@ -524,27 +562,44 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
524
562
  GPR_ASSERT(arg->type == GRPC_ARG_POINTER);
525
563
  grpc_client_channel_factory_ref(arg->value.pointer.p);
526
564
  chand->client_channel_factory = arg->value.pointer.p;
527
- // Instantiate resolver.
565
+ // Get server name to resolve, using proxy mapper if needed.
528
566
  arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI);
529
567
  GPR_ASSERT(arg != NULL);
530
568
  GPR_ASSERT(arg->type == GRPC_ARG_STRING);
531
- chand->resolver =
532
- grpc_resolver_create(exec_ctx, arg->value.string, args->channel_args,
533
- chand->interested_parties);
569
+ char *proxy_name = NULL;
570
+ grpc_channel_args *new_args = NULL;
571
+ grpc_proxy_mappers_map_name(exec_ctx, arg->value.string, args->channel_args,
572
+ &proxy_name, &new_args);
573
+ // Instantiate resolver.
574
+ chand->resolver = grpc_resolver_create(
575
+ exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
576
+ new_args != NULL ? new_args : args->channel_args,
577
+ chand->interested_parties, chand->combiner);
578
+ if (proxy_name != NULL) gpr_free(proxy_name);
579
+ if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
534
580
  if (chand->resolver == NULL) {
535
581
  return GRPC_ERROR_CREATE("resolver creation failed");
536
582
  }
537
583
  return GRPC_ERROR_NONE;
538
584
  }
539
585
 
586
+ static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
587
+ grpc_error *error) {
588
+ grpc_resolver *resolver = arg;
589
+ grpc_resolver_shutdown_locked(exec_ctx, resolver);
590
+ GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
591
+ }
592
+
540
593
  /* Destructor for channel_data */
541
594
  static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
542
595
  grpc_channel_element *elem) {
543
596
  channel_data *chand = elem->channel_data;
544
-
545
597
  if (chand->resolver != NULL) {
546
- grpc_resolver_shutdown(exec_ctx, chand->resolver);
547
- GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
598
+ grpc_closure_sched(
599
+ exec_ctx,
600
+ grpc_closure_create(shutdown_resolver_locked, chand->resolver,
601
+ grpc_combiner_scheduler(chand->combiner, false)),
602
+ GRPC_ERROR_NONE);
548
603
  }
549
604
  if (chand->client_channel_factory != NULL) {
550
605
  grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
@@ -555,14 +610,15 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
555
610
  chand->interested_parties);
556
611
  GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
557
612
  }
558
- gpr_free(chand->lb_policy_name);
559
- gpr_free(chand->service_config_json);
613
+ gpr_free(chand->info_lb_policy_name);
614
+ gpr_free(chand->info_service_config_json);
560
615
  if (chand->method_params_table != NULL) {
561
- grpc_mdstr_hash_table_unref(exec_ctx, chand->method_params_table);
616
+ grpc_slice_hash_table_unref(exec_ctx, chand->method_params_table);
562
617
  }
563
618
  grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
564
- grpc_pollset_set_destroy(chand->interested_parties);
565
- gpr_mu_destroy(&chand->mu);
619
+ grpc_pollset_set_destroy(exec_ctx, chand->interested_parties);
620
+ GRPC_COMBINER_UNREF(exec_ctx, chand->combiner, "client_channel");
621
+ gpr_mu_destroy(&chand->info_mu);
566
622
  }
567
623
 
568
624
  /*************************************************************************
@@ -593,10 +649,10 @@ typedef struct client_channel_call_data {
593
649
  // to avoid this without breaking the grpc_deadline_state abstraction.
594
650
  grpc_deadline_state deadline_state;
595
651
 
596
- grpc_mdstr *path; // Request path.
652
+ grpc_slice path; // Request path.
597
653
  gpr_timespec call_start_time;
598
654
  gpr_timespec deadline;
599
- wait_for_ready_value wait_for_ready_from_service_config;
655
+ method_parameters *method_params;
600
656
  grpc_closure read_service_config;
601
657
 
602
658
  grpc_error *cancel_error;
@@ -605,8 +661,6 @@ typedef struct client_channel_call_data {
605
661
  grpc_subchannel_call */
606
662
  gpr_atm subchannel_call;
607
663
 
608
- gpr_mu mu;
609
-
610
664
  subchannel_creation_phase creation_phase;
611
665
  grpc_connected_subchannel *connected_subchannel;
612
666
  grpc_polling_entity *pollent;
@@ -622,6 +676,12 @@ typedef struct client_channel_call_data {
622
676
  grpc_linked_mdelem lb_token_mdelem;
623
677
  } call_data;
624
678
 
679
+ grpc_subchannel_call *grpc_client_channel_get_subchannel_call(
680
+ grpc_call_element *call_elem) {
681
+ grpc_subchannel_call *scc = GET_CALL((call_data *)call_elem->call_data);
682
+ return scc == CANCELLED_CALL ? NULL : scc;
683
+ }
684
+
625
685
  static void add_waiting_locked(call_data *calld, grpc_transport_stream_op *op) {
626
686
  GPR_TIMER_BEGIN("add_waiting_locked", 0);
627
687
  if (calld->waiting_ops_count == calld->waiting_ops_capacity) {
@@ -645,52 +705,32 @@ static void fail_locked(grpc_exec_ctx *exec_ctx, call_data *calld,
645
705
  GRPC_ERROR_UNREF(error);
646
706
  }
647
707
 
648
- typedef struct {
649
- grpc_transport_stream_op **ops;
650
- size_t nops;
651
- grpc_subchannel_call *call;
652
- } retry_ops_args;
653
-
654
- static void retry_ops(grpc_exec_ctx *exec_ctx, void *args, grpc_error *error) {
655
- retry_ops_args *a = args;
656
- size_t i;
657
- for (i = 0; i < a->nops; i++) {
658
- grpc_subchannel_call_process_op(exec_ctx, a->call, a->ops[i]);
659
- }
660
- GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, a->call, "retry_ops");
661
- gpr_free(a->ops);
662
- gpr_free(a);
663
- }
664
-
665
708
  static void retry_waiting_locked(grpc_exec_ctx *exec_ctx, call_data *calld) {
666
709
  if (calld->waiting_ops_count == 0) {
667
710
  return;
668
711
  }
669
712
 
670
- retry_ops_args *a = gpr_malloc(sizeof(*a));
671
- a->ops = calld->waiting_ops;
672
- a->nops = calld->waiting_ops_count;
673
- a->call = GET_CALL(calld);
674
- if (a->call == CANCELLED_CALL) {
675
- gpr_free(a);
713
+ grpc_subchannel_call *call = GET_CALL(calld);
714
+ grpc_transport_stream_op **ops = calld->waiting_ops;
715
+ size_t nops = calld->waiting_ops_count;
716
+ if (call == CANCELLED_CALL) {
676
717
  fail_locked(exec_ctx, calld, GRPC_ERROR_CANCELLED);
677
718
  return;
678
719
  }
679
720
  calld->waiting_ops = NULL;
680
721
  calld->waiting_ops_count = 0;
681
722
  calld->waiting_ops_capacity = 0;
682
- GRPC_SUBCHANNEL_CALL_REF(a->call, "retry_ops");
683
- grpc_closure_sched(
684
- exec_ctx, grpc_closure_create(retry_ops, a, grpc_schedule_on_exec_ctx),
685
- GRPC_ERROR_NONE);
723
+ for (size_t i = 0; i < nops; i++) {
724
+ grpc_subchannel_call_process_op(exec_ctx, call, ops[i]);
725
+ }
726
+ gpr_free(ops);
686
727
  }
687
728
 
688
- static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
689
- grpc_error *error) {
729
+ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
730
+ grpc_error *error) {
690
731
  grpc_call_element *elem = arg;
691
732
  call_data *calld = elem->call_data;
692
733
  channel_data *chand = elem->channel_data;
693
- gpr_mu_lock(&calld->mu);
694
734
  GPR_ASSERT(calld->creation_phase ==
695
735
  GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
696
736
  grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent,
@@ -726,7 +766,6 @@ static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg,
726
766
  (gpr_atm)(uintptr_t)subchannel_call);
727
767
  retry_waiting_locked(exec_ctx, calld);
728
768
  }
729
- gpr_mu_unlock(&calld->mu);
730
769
  GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
731
770
  }
732
771
 
@@ -752,37 +791,35 @@ typedef struct {
752
791
  /** Return true if subchannel is available immediately (in which case on_ready
753
792
  should not be called), or false otherwise (in which case on_ready should be
754
793
  called when the subchannel is available). */
755
- static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
756
- grpc_metadata_batch *initial_metadata,
757
- uint32_t initial_metadata_flags,
758
- grpc_connected_subchannel **connected_subchannel,
759
- grpc_closure *on_ready, grpc_error *error);
760
-
761
- static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg,
762
- grpc_error *error) {
794
+ static bool pick_subchannel_locked(
795
+ grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
796
+ grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
797
+ grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
798
+ grpc_error *error);
799
+
800
+ static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg,
801
+ grpc_error *error) {
763
802
  continue_picking_args *cpa = arg;
764
803
  if (cpa->connected_subchannel == NULL) {
765
804
  /* cancelled, do nothing */
766
805
  } else if (error != GRPC_ERROR_NONE) {
767
806
  grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_REF(error));
768
807
  } else {
769
- call_data *calld = cpa->elem->call_data;
770
- gpr_mu_lock(&calld->mu);
771
- if (pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
772
- cpa->initial_metadata_flags, cpa->connected_subchannel,
773
- cpa->on_ready, GRPC_ERROR_NONE)) {
808
+ if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata,
809
+ cpa->initial_metadata_flags,
810
+ cpa->connected_subchannel, cpa->on_ready,
811
+ GRPC_ERROR_NONE)) {
774
812
  grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE);
775
813
  }
776
- gpr_mu_unlock(&calld->mu);
777
814
  }
778
815
  gpr_free(cpa);
779
816
  }
780
817
 
781
- static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
782
- grpc_metadata_batch *initial_metadata,
783
- uint32_t initial_metadata_flags,
784
- grpc_connected_subchannel **connected_subchannel,
785
- grpc_closure *on_ready, grpc_error *error) {
818
+ static bool pick_subchannel_locked(
819
+ grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
820
+ grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags,
821
+ grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready,
822
+ grpc_error *error) {
786
823
  GPR_TIMER_BEGIN("pick_subchannel", 0);
787
824
 
788
825
  channel_data *chand = elem->channel_data;
@@ -792,11 +829,11 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
792
829
 
793
830
  GPR_ASSERT(connected_subchannel);
794
831
 
795
- gpr_mu_lock(&chand->mu);
796
832
  if (initial_metadata == NULL) {
797
833
  if (chand->lb_policy != NULL) {
798
- grpc_lb_policy_cancel_pick(exec_ctx, chand->lb_policy,
799
- connected_subchannel, GRPC_ERROR_REF(error));
834
+ grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy,
835
+ connected_subchannel,
836
+ GRPC_ERROR_REF(error));
800
837
  }
801
838
  for (closure = chand->waiting_for_config_closures.head; closure != NULL;
802
839
  closure = closure->next_data.next) {
@@ -808,7 +845,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
808
845
  GRPC_ERROR_CREATE_REFERENCING("Pick cancelled", &error, 1));
809
846
  }
810
847
  }
811
- gpr_mu_unlock(&chand->mu);
812
848
  GPR_TIMER_END("pick_subchannel", 0);
813
849
  GRPC_ERROR_UNREF(error);
814
850
  return true;
@@ -817,7 +853,6 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
817
853
  if (chand->lb_policy != NULL) {
818
854
  grpc_lb_policy *lb_policy = chand->lb_policy;
819
855
  GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel");
820
- gpr_mu_unlock(&chand->mu);
821
856
  // If the application explicitly set wait_for_ready, use that.
822
857
  // Otherwise, if the service config specified a value for this
823
858
  // method, use that.
@@ -825,10 +860,11 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
825
860
  initial_metadata_flags &
826
861
  GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET;
827
862
  const bool wait_for_ready_set_from_service_config =
828
- calld->wait_for_ready_from_service_config != WAIT_FOR_READY_UNSET;
863
+ calld->method_params != NULL &&
864
+ calld->method_params->wait_for_ready != WAIT_FOR_READY_UNSET;
829
865
  if (!wait_for_ready_set_from_api &&
830
866
  wait_for_ready_set_from_service_config) {
831
- if (calld->wait_for_ready_from_service_config == WAIT_FOR_READY_TRUE) {
867
+ if (calld->method_params->wait_for_ready == WAIT_FOR_READY_TRUE) {
832
868
  initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
833
869
  } else {
834
870
  initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
@@ -837,7 +873,7 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
837
873
  const grpc_lb_policy_pick_args inputs = {
838
874
  initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
839
875
  gpr_inf_future(GPR_CLOCK_MONOTONIC)};
840
- const bool result = grpc_lb_policy_pick(
876
+ const bool result = grpc_lb_policy_pick_locked(
841
877
  exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, on_ready);
842
878
  GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick_subchannel");
843
879
  GPR_TIMER_END("pick_subchannel", 0);
@@ -846,8 +882,9 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
846
882
  if (chand->resolver != NULL && !chand->started_resolving) {
847
883
  chand->started_resolving = true;
848
884
  GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
849
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
850
- &chand->on_resolver_result_changed);
885
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
886
+ &chand->resolver_result,
887
+ &chand->on_resolver_result_changed);
851
888
  }
852
889
  if (chand->resolver != NULL) {
853
890
  cpa = gpr_malloc(sizeof(*cpa));
@@ -856,88 +893,66 @@ static bool pick_subchannel(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
856
893
  cpa->connected_subchannel = connected_subchannel;
857
894
  cpa->on_ready = on_ready;
858
895
  cpa->elem = elem;
859
- grpc_closure_init(&cpa->closure, continue_picking, cpa,
860
- grpc_schedule_on_exec_ctx);
896
+ grpc_closure_init(&cpa->closure, continue_picking_locked, cpa,
897
+ grpc_combiner_scheduler(chand->combiner, true));
861
898
  grpc_closure_list_append(&chand->waiting_for_config_closures, &cpa->closure,
862
899
  GRPC_ERROR_NONE);
863
900
  } else {
864
901
  grpc_closure_sched(exec_ctx, on_ready, GRPC_ERROR_CREATE("Disconnected"));
865
902
  }
866
- gpr_mu_unlock(&chand->mu);
867
903
 
868
904
  GPR_TIMER_END("pick_subchannel", 0);
869
905
  return false;
870
906
  }
871
907
 
872
- // The logic here is fairly complicated, due to (a) the fact that we
873
- // need to handle the case where we receive the send op before the
874
- // initial metadata op, and (b) the need for efficiency, especially in
875
- // the streaming case.
876
- // TODO(ctiller): Explain this more thoroughly.
877
- static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
878
- grpc_call_element *elem,
879
- grpc_transport_stream_op *op) {
880
- call_data *calld = elem->call_data;
908
+ static void start_transport_stream_op_locked_inner(grpc_exec_ctx *exec_ctx,
909
+ grpc_transport_stream_op *op,
910
+ grpc_call_element *elem) {
881
911
  channel_data *chand = elem->channel_data;
882
- GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
883
- grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
884
- /* try to (atomically) get the call */
885
- grpc_subchannel_call *call = GET_CALL(calld);
886
- GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
887
- if (call == CANCELLED_CALL) {
888
- grpc_transport_stream_op_finish_with_failure(
889
- exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
890
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
891
- return;
892
- }
893
- if (call != NULL) {
894
- grpc_subchannel_call_process_op(exec_ctx, call, op);
895
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
896
- return;
897
- }
898
- /* we failed; lock and figure out what to do */
899
- gpr_mu_lock(&calld->mu);
900
- retry:
912
+ call_data *calld = elem->call_data;
913
+ grpc_subchannel_call *call;
914
+
901
915
  /* need to recheck that another thread hasn't set the call */
902
916
  call = GET_CALL(calld);
903
917
  if (call == CANCELLED_CALL) {
904
- gpr_mu_unlock(&calld->mu);
905
918
  grpc_transport_stream_op_finish_with_failure(
906
919
  exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
907
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
920
+ /* early out */
908
921
  return;
909
922
  }
910
923
  if (call != NULL) {
911
- gpr_mu_unlock(&calld->mu);
912
924
  grpc_subchannel_call_process_op(exec_ctx, call, op);
913
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
925
+ /* early out */
914
926
  return;
915
927
  }
916
928
  /* if this is a cancellation, then we can raise our cancelled flag */
917
929
  if (op->cancel_error != GRPC_ERROR_NONE) {
918
930
  if (!gpr_atm_rel_cas(&calld->subchannel_call, 0,
919
931
  (gpr_atm)(uintptr_t)CANCELLED_CALL)) {
920
- goto retry;
932
+ /* recurse to retry */
933
+ start_transport_stream_op_locked_inner(exec_ctx, op, elem);
934
+ /* early out */
935
+ return;
921
936
  } else {
922
- // Stash a copy of cancel_error in our call data, so that we can use
923
- // it for subsequent operations. This ensures that if the call is
924
- // cancelled before any ops are passed down (e.g., if the deadline
925
- // is in the past when the call starts), we can return the right
926
- // error to the caller when the first op does get passed down.
937
+ /* Stash a copy of cancel_error in our call data, so that we can use
938
+ it for subsequent operations. This ensures that if the call is
939
+ cancelled before any ops are passed down (e.g., if the deadline
940
+ is in the past when the call starts), we can return the right
941
+ error to the caller when the first op does get passed down. */
927
942
  calld->cancel_error = GRPC_ERROR_REF(op->cancel_error);
928
943
  switch (calld->creation_phase) {
929
944
  case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING:
930
945
  fail_locked(exec_ctx, calld, GRPC_ERROR_REF(op->cancel_error));
931
946
  break;
932
947
  case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
933
- pick_subchannel(exec_ctx, elem, NULL, 0, &calld->connected_subchannel,
934
- NULL, GRPC_ERROR_REF(op->cancel_error));
948
+ pick_subchannel_locked(exec_ctx, elem, NULL, 0,
949
+ &calld->connected_subchannel, NULL,
950
+ GRPC_ERROR_REF(op->cancel_error));
935
951
  break;
936
952
  }
937
- gpr_mu_unlock(&calld->mu);
938
953
  grpc_transport_stream_op_finish_with_failure(
939
954
  exec_ctx, op, GRPC_ERROR_REF(op->cancel_error));
940
- GPR_TIMER_END("cc_start_transport_stream_op", 0);
955
+ /* early out */
941
956
  return;
942
957
  }
943
958
  }
@@ -946,16 +961,16 @@ retry:
946
961
  calld->connected_subchannel == NULL &&
947
962
  op->send_initial_metadata != NULL) {
948
963
  calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL;
949
- grpc_closure_init(&calld->next_step, subchannel_ready, elem,
950
- grpc_schedule_on_exec_ctx);
964
+ grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem,
965
+ grpc_combiner_scheduler(chand->combiner, true));
951
966
  GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel");
952
967
  /* If a subchannel is not available immediately, the polling entity from
953
968
  call_data should be provided to channel_data's interested_parties, so
954
969
  that IO of the lb_policy and resolver could be done under it. */
955
- if (pick_subchannel(exec_ctx, elem, op->send_initial_metadata,
956
- op->send_initial_metadata_flags,
957
- &calld->connected_subchannel, &calld->next_step,
958
- GRPC_ERROR_NONE)) {
970
+ if (pick_subchannel_locked(exec_ctx, elem, op->send_initial_metadata,
971
+ op->send_initial_metadata_flags,
972
+ &calld->connected_subchannel, &calld->next_step,
973
+ GRPC_ERROR_NONE)) {
959
974
  calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
960
975
  GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel");
961
976
  } else {
@@ -978,131 +993,181 @@ retry:
978
993
  gpr_atm_rel_store(&calld->subchannel_call,
979
994
  (gpr_atm)(uintptr_t)subchannel_call);
980
995
  retry_waiting_locked(exec_ctx, calld);
981
- goto retry;
996
+ /* recurse to retry */
997
+ start_transport_stream_op_locked_inner(exec_ctx, op, elem);
998
+ /* early out */
999
+ return;
982
1000
  }
983
1001
  /* nothing to be done but wait */
984
1002
  add_waiting_locked(calld, op);
985
- gpr_mu_unlock(&calld->mu);
1003
+ }
1004
+
1005
+ static void start_transport_stream_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
1006
+ grpc_error *error_ignored) {
1007
+ GPR_TIMER_BEGIN("start_transport_stream_op_locked", 0);
1008
+
1009
+ grpc_transport_stream_op *op = arg;
1010
+ grpc_call_element *elem = op->handler_private.args[0];
1011
+ call_data *calld = elem->call_data;
1012
+
1013
+ start_transport_stream_op_locked_inner(exec_ctx, op, elem);
1014
+
1015
+ GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1016
+ "start_transport_stream_op");
1017
+ GPR_TIMER_END("start_transport_stream_op_locked", 0);
1018
+ }
1019
+
1020
+ /* The logic here is fairly complicated, due to (a) the fact that we
1021
+ need to handle the case where we receive the send op before the
1022
+ initial metadata op, and (b) the need for efficiency, especially in
1023
+ the streaming case.
1024
+
1025
+ We use double-checked locking to initially see if initialization has been
1026
+ performed. If it has not, we acquire the combiner and perform initialization.
1027
+ If it has, we proceed on the fast path. */
1028
+ static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
1029
+ grpc_call_element *elem,
1030
+ grpc_transport_stream_op *op) {
1031
+ call_data *calld = elem->call_data;
1032
+ channel_data *chand = elem->channel_data;
1033
+ GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
1034
+ grpc_deadline_state_client_start_transport_stream_op(exec_ctx, elem, op);
1035
+ /* try to (atomically) get the call */
1036
+ grpc_subchannel_call *call = GET_CALL(calld);
1037
+ GPR_TIMER_BEGIN("cc_start_transport_stream_op", 0);
1038
+ if (call == CANCELLED_CALL) {
1039
+ grpc_transport_stream_op_finish_with_failure(
1040
+ exec_ctx, op, GRPC_ERROR_REF(calld->cancel_error));
1041
+ GPR_TIMER_END("cc_start_transport_stream_op", 0);
1042
+ /* early out */
1043
+ return;
1044
+ }
1045
+ if (call != NULL) {
1046
+ grpc_subchannel_call_process_op(exec_ctx, call, op);
1047
+ GPR_TIMER_END("cc_start_transport_stream_op", 0);
1048
+ /* early out */
1049
+ return;
1050
+ }
1051
+ /* we failed; lock and figure out what to do */
1052
+ GRPC_CALL_STACK_REF(calld->owning_call, "start_transport_stream_op");
1053
+ op->handler_private.args[0] = elem;
1054
+ grpc_closure_sched(
1055
+ exec_ctx,
1056
+ grpc_closure_init(&op->handler_private.closure,
1057
+ start_transport_stream_op_locked, op,
1058
+ grpc_combiner_scheduler(chand->combiner, false)),
1059
+ GRPC_ERROR_NONE);
986
1060
  GPR_TIMER_END("cc_start_transport_stream_op", 0);
987
1061
  }
988
1062
 
1063
+ // Sets calld->method_params.
1064
+ // If the method params specify a timeout, populates
1065
+ // *per_method_deadline and returns true.
1066
+ static bool set_call_method_params_from_service_config_locked(
1067
+ grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
1068
+ gpr_timespec *per_method_deadline) {
1069
+ channel_data *chand = elem->channel_data;
1070
+ call_data *calld = elem->call_data;
1071
+ if (chand->method_params_table != NULL) {
1072
+ calld->method_params = grpc_method_config_table_get(
1073
+ exec_ctx, chand->method_params_table, calld->path);
1074
+ if (calld->method_params != NULL) {
1075
+ method_parameters_ref(calld->method_params);
1076
+ if (gpr_time_cmp(calld->method_params->timeout,
1077
+ gpr_time_0(GPR_TIMESPAN)) != 0) {
1078
+ *per_method_deadline =
1079
+ gpr_time_add(calld->call_start_time, calld->method_params->timeout);
1080
+ return true;
1081
+ }
1082
+ }
1083
+ }
1084
+ return false;
1085
+ }
1086
+
989
1087
  // Gets data from the service config. Invoked when the resolver returns
990
1088
  // its initial result.
991
- static void read_service_config(grpc_exec_ctx *exec_ctx, void *arg,
992
- grpc_error *error) {
1089
+ static void read_service_config_locked(grpc_exec_ctx *exec_ctx, void *arg,
1090
+ grpc_error *error) {
993
1091
  grpc_call_element *elem = arg;
994
- channel_data *chand = elem->channel_data;
995
1092
  call_data *calld = elem->call_data;
996
1093
  // If this is an error, there's no point in looking at the service config.
997
1094
  if (error == GRPC_ERROR_NONE) {
998
- // Get the method config table from channel data.
999
- gpr_mu_lock(&chand->mu);
1000
- grpc_mdstr_hash_table *method_params_table = NULL;
1001
- if (chand->method_params_table != NULL) {
1002
- method_params_table =
1003
- grpc_mdstr_hash_table_ref(chand->method_params_table);
1004
- }
1005
- gpr_mu_unlock(&chand->mu);
1006
- // If the method config table was present, use it.
1007
- if (method_params_table != NULL) {
1008
- const method_parameters *method_params = grpc_method_config_table_get(
1009
- exec_ctx, method_params_table, calld->path);
1010
- if (method_params != NULL) {
1011
- const bool have_method_timeout =
1012
- gpr_time_cmp(method_params->timeout, gpr_time_0(GPR_TIMESPAN)) != 0;
1013
- if (have_method_timeout ||
1014
- method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
1015
- gpr_mu_lock(&calld->mu);
1016
- if (have_method_timeout) {
1017
- const gpr_timespec per_method_deadline =
1018
- gpr_time_add(calld->call_start_time, method_params->timeout);
1019
- if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1020
- calld->deadline = per_method_deadline;
1021
- // Reset deadline timer.
1022
- grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
1023
- }
1024
- }
1025
- if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
1026
- calld->wait_for_ready_from_service_config =
1027
- method_params->wait_for_ready;
1028
- }
1029
- gpr_mu_unlock(&calld->mu);
1030
- }
1095
+ gpr_timespec per_method_deadline;
1096
+ if (set_call_method_params_from_service_config_locked(
1097
+ exec_ctx, elem, &per_method_deadline)) {
1098
+ // If the deadline from the service config is shorter than the one
1099
+ // from the client API, reset the deadline timer.
1100
+ if (gpr_time_cmp(per_method_deadline, calld->deadline) < 0) {
1101
+ calld->deadline = per_method_deadline;
1102
+ grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
1031
1103
  }
1032
- grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
1033
1104
  }
1034
1105
  }
1035
1106
  GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "read_service_config");
1036
1107
  }
1037
1108
 
1038
- /* Constructor for call_data */
1039
- static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1040
- grpc_call_element *elem,
1041
- grpc_call_element_args *args) {
1109
+ static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
1110
+ void *arg,
1111
+ grpc_error *error_ignored) {
1112
+ grpc_call_element *elem = arg;
1042
1113
  channel_data *chand = elem->channel_data;
1043
1114
  call_data *calld = elem->call_data;
1044
- // Initialize data members.
1045
- grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
1046
- calld->path = GRPC_MDSTR_REF(args->path);
1047
- calld->call_start_time = args->start_time;
1048
- calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1049
- calld->wait_for_ready_from_service_config = WAIT_FOR_READY_UNSET;
1050
- calld->cancel_error = GRPC_ERROR_NONE;
1051
- gpr_atm_rel_store(&calld->subchannel_call, 0);
1052
- gpr_mu_init(&calld->mu);
1053
- calld->connected_subchannel = NULL;
1054
- calld->waiting_ops = NULL;
1055
- calld->waiting_ops_count = 0;
1056
- calld->waiting_ops_capacity = 0;
1057
- calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1058
- calld->owning_call = args->call_stack;
1059
- calld->pollent = NULL;
1060
1115
  // If the resolver has already returned results, then we can access
1061
1116
  // the service config parameters immediately. Otherwise, we need to
1062
1117
  // defer that work until the resolver returns an initial result.
1063
- // TODO(roth): This code is almost but not quite identical to the code
1064
- // in read_service_config() above. It would be nice to find a way to
1065
- // combine them, to avoid having to maintain it twice.
1066
- gpr_mu_lock(&chand->mu);
1067
1118
  if (chand->lb_policy != NULL) {
1068
1119
  // We already have a resolver result, so check for service config.
1069
- if (chand->method_params_table != NULL) {
1070
- grpc_mdstr_hash_table *method_params_table =
1071
- grpc_mdstr_hash_table_ref(chand->method_params_table);
1072
- gpr_mu_unlock(&chand->mu);
1073
- method_parameters *method_params = grpc_method_config_table_get(
1074
- exec_ctx, method_params_table, args->path);
1075
- if (method_params != NULL) {
1076
- if (gpr_time_cmp(method_params->timeout,
1077
- gpr_time_0(GPR_CLOCK_MONOTONIC)) != 0) {
1078
- gpr_timespec per_method_deadline =
1079
- gpr_time_add(calld->call_start_time, method_params->timeout);
1080
- calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
1081
- }
1082
- if (method_params->wait_for_ready != WAIT_FOR_READY_UNSET) {
1083
- calld->wait_for_ready_from_service_config =
1084
- method_params->wait_for_ready;
1085
- }
1086
- }
1087
- grpc_mdstr_hash_table_unref(exec_ctx, method_params_table);
1088
- } else {
1089
- gpr_mu_unlock(&chand->mu);
1120
+ gpr_timespec per_method_deadline;
1121
+ if (set_call_method_params_from_service_config_locked(
1122
+ exec_ctx, elem, &per_method_deadline)) {
1123
+ calld->deadline = gpr_time_min(calld->deadline, per_method_deadline);
1090
1124
  }
1091
1125
  } else {
1092
1126
  // We don't yet have a resolver result, so register a callback to
1093
1127
  // get the service config data once the resolver returns.
1094
1128
  // Take a reference to the call stack to be owned by the callback.
1095
1129
  GRPC_CALL_STACK_REF(calld->owning_call, "read_service_config");
1096
- grpc_closure_init(&calld->read_service_config, read_service_config, elem,
1097
- grpc_schedule_on_exec_ctx);
1130
+ grpc_closure_init(&calld->read_service_config, read_service_config_locked,
1131
+ elem, grpc_combiner_scheduler(chand->combiner, false));
1098
1132
  grpc_closure_list_append(&chand->waiting_for_config_closures,
1099
1133
  &calld->read_service_config, GRPC_ERROR_NONE);
1100
- gpr_mu_unlock(&chand->mu);
1101
1134
  }
1102
1135
  // Start the deadline timer with the current deadline value. If we
1103
1136
  // do not yet have service config data, then the timer may be reset
1104
1137
  // later.
1105
1138
  grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
1139
+ GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call,
1140
+ "initial_read_service_config");
1141
+ }
1142
+
1143
+ /* Constructor for call_data */
1144
+ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
1145
+ grpc_call_element *elem,
1146
+ const grpc_call_element_args *args) {
1147
+ channel_data *chand = elem->channel_data;
1148
+ call_data *calld = elem->call_data;
1149
+ // Initialize data members.
1150
+ grpc_deadline_state_init(exec_ctx, elem, args->call_stack);
1151
+ calld->path = grpc_slice_ref_internal(args->path);
1152
+ calld->call_start_time = args->start_time;
1153
+ calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
1154
+ calld->method_params = NULL;
1155
+ calld->cancel_error = GRPC_ERROR_NONE;
1156
+ gpr_atm_rel_store(&calld->subchannel_call, 0);
1157
+ calld->connected_subchannel = NULL;
1158
+ calld->waiting_ops = NULL;
1159
+ calld->waiting_ops_count = 0;
1160
+ calld->waiting_ops_capacity = 0;
1161
+ calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
1162
+ calld->owning_call = args->call_stack;
1163
+ calld->pollent = NULL;
1164
+ GRPC_CALL_STACK_REF(calld->owning_call, "initial_read_service_config");
1165
+ grpc_closure_sched(
1166
+ exec_ctx,
1167
+ grpc_closure_init(&calld->read_service_config,
1168
+ initial_read_service_config_locked, elem,
1169
+ grpc_combiner_scheduler(chand->combiner, false)),
1170
+ GRPC_ERROR_NONE);
1106
1171
  return GRPC_ERROR_NONE;
1107
1172
  }
1108
1173
 
@@ -1113,14 +1178,16 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx,
1113
1178
  void *and_free_memory) {
1114
1179
  call_data *calld = elem->call_data;
1115
1180
  grpc_deadline_state_destroy(exec_ctx, elem);
1116
- GRPC_MDSTR_UNREF(exec_ctx, calld->path);
1181
+ grpc_slice_unref_internal(exec_ctx, calld->path);
1182
+ if (calld->method_params != NULL) {
1183
+ method_parameters_unref(calld->method_params);
1184
+ }
1117
1185
  GRPC_ERROR_UNREF(calld->cancel_error);
1118
1186
  grpc_subchannel_call *call = GET_CALL(calld);
1119
1187
  if (call != NULL && call != CANCELLED_CALL) {
1120
1188
  GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call");
1121
1189
  }
1122
1190
  GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING);
1123
- gpr_mu_destroy(&calld->mu);
1124
1191
  GPR_ASSERT(calld->waiting_ops_count == 0);
1125
1192
  if (calld->connected_subchannel != NULL) {
1126
1193
  GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel,
@@ -1156,26 +1223,37 @@ const grpc_channel_filter grpc_client_channel_filter = {
1156
1223
  "client-channel",
1157
1224
  };
1158
1225
 
1226
+ static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
1227
+ grpc_error *error_ignored) {
1228
+ channel_data *chand = arg;
1229
+ if (chand->lb_policy != NULL) {
1230
+ grpc_lb_policy_exit_idle_locked(exec_ctx, chand->lb_policy);
1231
+ } else {
1232
+ chand->exit_idle_when_lb_policy_arrives = true;
1233
+ if (!chand->started_resolving && chand->resolver != NULL) {
1234
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1235
+ chand->started_resolving = true;
1236
+ grpc_resolver_next_locked(exec_ctx, chand->resolver,
1237
+ &chand->resolver_result,
1238
+ &chand->on_resolver_result_changed);
1239
+ }
1240
+ }
1241
+ GRPC_CHANNEL_STACK_UNREF(exec_ctx, chand->owning_stack, "try_to_connect");
1242
+ }
1243
+
1159
1244
  grpc_connectivity_state grpc_client_channel_check_connectivity_state(
1160
1245
  grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
1161
1246
  channel_data *chand = elem->channel_data;
1162
- grpc_connectivity_state out;
1163
- gpr_mu_lock(&chand->mu);
1164
- out = grpc_connectivity_state_check(&chand->state_tracker, NULL);
1247
+ grpc_connectivity_state out =
1248
+ grpc_connectivity_state_check(&chand->state_tracker);
1165
1249
  if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
1166
- if (chand->lb_policy != NULL) {
1167
- grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
1168
- } else {
1169
- chand->exit_idle_when_lb_policy_arrives = true;
1170
- if (!chand->started_resolving && chand->resolver != NULL) {
1171
- GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
1172
- chand->started_resolving = true;
1173
- grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result,
1174
- &chand->on_resolver_result_changed);
1175
- }
1176
- }
1250
+ GRPC_CHANNEL_STACK_REF(chand->owning_stack, "try_to_connect");
1251
+ grpc_closure_sched(
1252
+ exec_ctx,
1253
+ grpc_closure_create(try_to_connect_locked, chand,
1254
+ grpc_combiner_scheduler(chand->combiner, false)),
1255
+ GRPC_ERROR_NONE);
1177
1256
  }
1178
- gpr_mu_unlock(&chand->mu);
1179
1257
  return out;
1180
1258
  }
1181
1259
 
@@ -1183,6 +1261,7 @@ typedef struct {
1183
1261
  channel_data *chand;
1184
1262
  grpc_pollset *pollset;
1185
1263
  grpc_closure *on_complete;
1264
+ grpc_connectivity_state *state;
1186
1265
  grpc_closure my_closure;
1187
1266
  } external_connectivity_watcher;
1188
1267
 
@@ -1195,7 +1274,16 @@ static void on_external_watch_complete(grpc_exec_ctx *exec_ctx, void *arg,
1195
1274
  GRPC_CHANNEL_STACK_UNREF(exec_ctx, w->chand->owning_stack,
1196
1275
  "external_connectivity_watcher");
1197
1276
  gpr_free(w);
1198
- follow_up->cb(exec_ctx, follow_up->cb_arg, error);
1277
+ grpc_closure_run(exec_ctx, follow_up, GRPC_ERROR_REF(error));
1278
+ }
1279
+
1280
+ static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg,
1281
+ grpc_error *error_ignored) {
1282
+ external_connectivity_watcher *w = arg;
1283
+ grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1284
+ grpc_schedule_on_exec_ctx);
1285
+ grpc_connectivity_state_notify_on_state_change(
1286
+ exec_ctx, &w->chand->state_tracker, w->state, &w->my_closure);
1199
1287
  }
1200
1288
 
1201
1289
  void grpc_client_channel_watch_connectivity_state(
@@ -1206,13 +1294,13 @@ void grpc_client_channel_watch_connectivity_state(
1206
1294
  w->chand = chand;
1207
1295
  w->pollset = pollset;
1208
1296
  w->on_complete = on_complete;
1297
+ w->state = state;
1209
1298
  grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset);
1210
- grpc_closure_init(&w->my_closure, on_external_watch_complete, w,
1211
- grpc_schedule_on_exec_ctx);
1212
1299
  GRPC_CHANNEL_STACK_REF(w->chand->owning_stack,
1213
1300
  "external_connectivity_watcher");
1214
- gpr_mu_lock(&chand->mu);
1215
- grpc_connectivity_state_notify_on_state_change(
1216
- exec_ctx, &chand->state_tracker, state, &w->my_closure);
1217
- gpr_mu_unlock(&chand->mu);
1301
+ grpc_closure_sched(
1302
+ exec_ctx,
1303
+ grpc_closure_init(&w->my_closure, watch_connectivity_state_locked, w,
1304
+ grpc_combiner_scheduler(chand->combiner, true)),
1305
+ GRPC_ERROR_NONE);
1218
1306
  }