grpc 1.23.1 → 1.24.0.pre1

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

Potentially problematic release.


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

Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +757 -477
  3. data/include/grpc/grpc.h +3 -1
  4. data/include/grpc/grpc_security.h +20 -4
  5. data/include/grpc/impl/codegen/grpc_types.h +6 -5
  6. data/include/grpc/impl/codegen/port_platform.h +25 -0
  7. data/src/core/ext/filters/client_channel/backend_metric.cc +78 -0
  8. data/src/core/ext/filters/client_channel/backend_metric.h +36 -0
  9. data/src/core/ext/filters/client_channel/channel_connectivity.cc +16 -2
  10. data/src/core/ext/filters/client_channel/client_channel.cc +325 -267
  11. data/src/core/ext/filters/client_channel/client_channel_factory.h +0 -4
  12. data/src/core/ext/filters/client_channel/health/health_check_client.cc +23 -32
  13. data/src/core/ext/filters/client_channel/http_proxy.cc +7 -3
  14. data/src/core/ext/filters/client_channel/lb_policy.cc +1 -1
  15. data/src/core/ext/filters/client_channel/lb_policy.h +58 -34
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +46 -50
  17. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +9 -2
  18. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +35 -17
  19. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +130 -215
  20. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +34 -21
  21. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +1120 -802
  22. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h +8 -2
  23. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_secure.cc +33 -12
  24. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.cc +151 -40
  25. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h +184 -26
  26. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.cc +389 -245
  27. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_load_balancer_api.h +98 -60
  28. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +6 -1
  29. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +89 -0
  30. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +3 -8
  31. data/src/core/ext/filters/client_channel/server_address.cc +1 -3
  32. data/src/core/ext/filters/client_channel/server_address.h +1 -1
  33. data/src/core/ext/filters/client_channel/subchannel.h +2 -1
  34. data/src/core/ext/filters/client_idle/client_idle_filter.cc +207 -29
  35. data/src/core/ext/filters/http/client/http_client_filter.cc +10 -8
  36. data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
  37. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +10 -7
  38. data/src/core/ext/filters/http/server/http_server_filter.cc +52 -26
  39. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +23 -20
  40. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +24 -21
  41. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +1 -1
  42. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +37 -24
  43. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +1 -0
  44. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +237 -191
  45. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +29 -27
  46. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +1 -1
  47. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +19 -4
  48. data/src/core/ext/transport/chttp2/transport/hpack_table.h +13 -4
  49. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +2 -1
  50. data/src/core/ext/transport/chttp2/transport/internal.h +0 -2
  51. data/src/core/ext/transport/chttp2/transport/parsing.cc +99 -71
  52. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c +222 -0
  53. data/src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h +818 -0
  54. data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.c +314 -0
  55. data/src/core/ext/upb-generated/envoy/api/v2/cds.upb.h +1142 -0
  56. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c +53 -0
  57. data/src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h +158 -0
  58. data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.c +34 -0
  59. data/src/core/ext/upb-generated/envoy/api/v2/cluster/filter.upb.h +69 -0
  60. data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c +49 -0
  61. data/src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h +240 -0
  62. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.c +110 -0
  63. data/src/core/ext/upb-generated/envoy/api/v2/core/address.upb.h +324 -0
  64. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.c +235 -0
  65. data/src/core/ext/upb-generated/envoy/api/v2/core/base.upb.h +661 -0
  66. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.c +84 -0
  67. data/src/core/ext/upb-generated/envoy/api/v2/core/config_source.upb.h +274 -0
  68. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.c +175 -0
  69. data/src/core/ext/upb-generated/envoy/api/v2/core/grpc_service.upb.h +572 -0
  70. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.c +150 -0
  71. data/src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h +596 -0
  72. data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.c +35 -0
  73. data/src/core/ext/upb-generated/envoy/api/v2/core/http_uri.upb.h +80 -0
  74. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.c +95 -0
  75. data/src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h +308 -0
  76. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c +128 -0
  77. data/src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h +392 -0
  78. data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.c +91 -0
  79. data/src/core/ext/upb-generated/envoy/api/v2/eds.upb.h +236 -0
  80. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c +88 -0
  81. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h +258 -0
  82. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c +111 -0
  83. data/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h +324 -0
  84. data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c +23 -0
  85. data/src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h +50 -0
  86. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c +52 -0
  87. data/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h +130 -0
  88. data/src/core/ext/upb-generated/envoy/type/percent.upb.c +39 -0
  89. data/src/core/ext/upb-generated/envoy/type/percent.upb.h +87 -0
  90. data/src/core/ext/upb-generated/envoy/type/range.upb.c +39 -0
  91. data/src/core/ext/upb-generated/envoy/type/range.upb.h +85 -0
  92. data/src/core/ext/upb-generated/gogoproto/gogo.upb.c +17 -0
  93. data/src/core/ext/upb-generated/gogoproto/gogo.upb.h +30 -0
  94. data/src/core/ext/upb-generated/google/api/annotations.upb.c +18 -0
  95. data/src/core/ext/upb-generated/google/api/annotations.upb.h +30 -0
  96. data/src/core/ext/upb-generated/google/api/http.upb.c +66 -0
  97. data/src/core/ext/upb-generated/google/api/http.upb.h +190 -0
  98. data/src/core/ext/upb-generated/google/protobuf/any.upb.c +27 -0
  99. data/src/core/ext/upb-generated/google/protobuf/any.upb.h +58 -0
  100. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.c +485 -0
  101. data/src/core/ext/upb-generated/google/protobuf/descriptor.upb.h +1690 -0
  102. data/src/core/ext/upb-generated/google/protobuf/duration.upb.c +27 -0
  103. data/src/core/ext/upb-generated/google/protobuf/duration.upb.h +58 -0
  104. data/src/core/ext/upb-generated/google/protobuf/empty.upb.c +22 -0
  105. data/src/core/ext/upb-generated/google/protobuf/empty.upb.h +50 -0
  106. data/src/core/ext/upb-generated/google/protobuf/struct.upb.c +79 -0
  107. data/src/core/ext/upb-generated/google/protobuf/struct.upb.h +215 -0
  108. data/src/core/ext/upb-generated/google/protobuf/timestamp.upb.c +27 -0
  109. data/src/core/ext/upb-generated/google/protobuf/timestamp.upb.h +58 -0
  110. data/src/core/ext/upb-generated/google/protobuf/wrappers.upb.c +106 -0
  111. data/src/core/ext/upb-generated/google/protobuf/wrappers.upb.h +238 -0
  112. data/src/core/ext/upb-generated/google/rpc/status.upb.c +33 -0
  113. data/src/core/ext/upb-generated/google/rpc/status.upb.h +74 -0
  114. data/src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c +49 -0
  115. data/src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h +126 -0
  116. data/src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c +209 -0
  117. data/src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h +681 -0
  118. data/src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c +42 -0
  119. data/src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h +109 -0
  120. data/src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c +36 -0
  121. data/src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h +84 -0
  122. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c +133 -0
  123. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h +359 -0
  124. data/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c +58 -0
  125. data/src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h +144 -0
  126. data/src/core/ext/upb-generated/validate/validate.upb.c +443 -0
  127. data/src/core/ext/upb-generated/validate/validate.upb.h +2037 -0
  128. data/src/core/lib/channel/channel_args.cc +21 -0
  129. data/src/core/lib/channel/channel_args.h +16 -2
  130. data/src/core/lib/channel/channel_stack.h +2 -1
  131. data/src/core/lib/channel/channelz.cc +54 -56
  132. data/src/core/lib/channel/channelz.h +29 -12
  133. data/src/core/lib/compression/compression.cc +2 -1
  134. data/src/core/lib/compression/compression_internal.h +8 -0
  135. data/src/core/lib/gpr/log_linux.cc +2 -2
  136. data/src/core/lib/gpr/log_posix.cc +2 -2
  137. data/src/core/lib/gpr/time_precise.cc +123 -36
  138. data/src/core/lib/gpr/time_precise.h +37 -0
  139. data/src/core/lib/gprpp/abstract.h +10 -0
  140. data/src/core/lib/gprpp/atomic.h +4 -0
  141. data/src/core/lib/gprpp/inlined_vector.h +20 -4
  142. data/src/core/lib/gprpp/map.h +109 -6
  143. data/src/core/lib/gprpp/memory.h +6 -0
  144. data/src/core/lib/gprpp/ref_counted_ptr.h +2 -0
  145. data/src/core/lib/iomgr/ev_epollex_linux.cc +29 -54
  146. data/src/core/lib/iomgr/exec_ctx.cc +27 -17
  147. data/src/core/lib/iomgr/exec_ctx.h +3 -0
  148. data/src/core/lib/iomgr/sockaddr_utils.cc +1 -3
  149. data/src/core/lib/iomgr/tcp_posix.cc +16 -25
  150. data/src/core/lib/iomgr/tcp_server_custom.cc +1 -1
  151. data/src/core/lib/iomgr/timer_manager.cc +8 -1
  152. data/src/core/lib/iomgr/timer_manager.h +2 -0
  153. data/src/core/lib/security/credentials/credentials.h +8 -2
  154. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +23 -0
  155. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +3 -0
  156. data/src/core/lib/security/credentials/tls/spiffe_credentials.cc +3 -3
  157. data/src/core/lib/security/security_connector/ssl_utils.cc +1 -12
  158. data/src/core/lib/security/security_connector/ssl_utils.h +10 -6
  159. data/src/core/lib/security/security_connector/ssl_utils_config.cc +32 -0
  160. data/src/core/lib/security/security_connector/ssl_utils_config.h +30 -0
  161. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.cc +161 -49
  162. data/src/core/lib/security/security_connector/tls/spiffe_security_connector.h +34 -1
  163. data/src/core/lib/slice/slice_intern.cc +17 -9
  164. data/src/core/lib/slice/slice_internal.h +34 -7
  165. data/src/core/lib/slice/slice_utils.h +7 -3
  166. data/src/core/lib/surface/call.cc +97 -57
  167. data/src/core/lib/surface/channel.cc +2 -2
  168. data/src/core/lib/surface/completion_queue.cc +10 -16
  169. data/src/core/lib/surface/init.cc +3 -0
  170. data/src/core/lib/surface/server.cc +11 -14
  171. data/src/core/lib/surface/validate_metadata.cc +4 -0
  172. data/src/core/lib/surface/version.cc +2 -2
  173. data/src/core/lib/transport/metadata.cc +4 -4
  174. data/src/core/lib/transport/metadata_batch.cc +72 -16
  175. data/src/core/lib/transport/metadata_batch.h +38 -0
  176. data/src/core/lib/transport/static_metadata.cc +814 -1023
  177. data/src/core/lib/transport/static_metadata.h +271 -213
  178. data/src/core/lib/transport/transport.h +12 -0
  179. data/src/core/plugin_registry/grpc_plugin_registry.cc +4 -0
  180. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +104 -76
  181. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +34 -16
  182. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +2 -2
  183. data/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +10 -6
  184. data/src/core/tsi/alts/handshaker/alts_tsi_utils.h +4 -3
  185. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +74 -48
  186. data/src/core/tsi/alts/handshaker/transport_security_common_api.h +34 -26
  187. data/src/core/tsi/ssl_transport_security.cc +14 -6
  188. data/src/core/tsi/ssl_transport_security.h +4 -0
  189. data/src/ruby/ext/grpc/ext-export.clang +1 -0
  190. data/src/ruby/ext/grpc/ext-export.gcc +6 -0
  191. data/src/ruby/ext/grpc/extconf.rb +5 -0
  192. data/src/ruby/ext/grpc/rb_enable_cpp.cc +22 -0
  193. data/src/ruby/ext/grpc/rb_grpc.c +1 -42
  194. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -0
  195. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +6 -0
  196. data/src/ruby/lib/grpc.rb +2 -0
  197. data/src/ruby/lib/grpc/core/status_codes.rb +135 -0
  198. data/src/ruby/lib/grpc/errors.rb +4 -7
  199. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +9 -4
  200. data/src/ruby/lib/grpc/structs.rb +15 -0
  201. data/src/ruby/lib/grpc/version.rb +1 -1
  202. data/src/ruby/spec/errors_spec.rb +1 -0
  203. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_import.proto +22 -0
  204. data/src/ruby/spec/pb/codegen/grpc/testing/package_options_ruby_style.proto +34 -0
  205. data/src/ruby/spec/pb/codegen/package_option_spec.rb +53 -29
  206. data/third_party/upb/upb/decode.c +604 -0
  207. data/third_party/upb/upb/decode.h +21 -0
  208. data/third_party/upb/upb/encode.c +378 -0
  209. data/third_party/upb/upb/encode.h +21 -0
  210. data/third_party/upb/upb/generated_util.h +105 -0
  211. data/third_party/upb/upb/msg.c +111 -0
  212. data/third_party/upb/upb/msg.h +69 -0
  213. data/third_party/upb/upb/port.c +27 -0
  214. data/third_party/upb/upb/port_def.inc +152 -0
  215. data/third_party/upb/upb/port_undef.inc +21 -0
  216. data/third_party/upb/upb/table.c +911 -0
  217. data/third_party/upb/upb/table.int.h +507 -0
  218. data/third_party/upb/upb/upb.c +261 -0
  219. data/third_party/upb/upb/upb.h +364 -0
  220. metadata +134 -55
  221. data/src/core/ext/filters/client_channel/health/health.pb.c +0 -23
  222. data/src/core/ext/filters/client_channel/health/health.pb.h +0 -73
  223. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.c +0 -19
  224. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/duration.pb.h +0 -54
  225. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.c +0 -19
  226. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/google/protobuf/timestamp.pb.h +0 -54
  227. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +0 -89
  228. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +0 -164
  229. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc +0 -520
  230. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api.h +0 -323
  231. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc +0 -145
  232. data/src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h +0 -149
  233. data/src/core/tsi/alts/handshaker/altscontext.pb.c +0 -47
  234. data/src/core/tsi/alts/handshaker/altscontext.pb.h +0 -63
  235. data/src/core/tsi/alts/handshaker/handshaker.pb.c +0 -122
  236. data/src/core/tsi/alts/handshaker/handshaker.pb.h +0 -254
  237. data/src/core/tsi/alts/handshaker/transport_security_common.pb.c +0 -49
  238. data/src/core/tsi/alts/handshaker/transport_security_common.pb.h +0 -78
  239. data/third_party/nanopb/pb.h +0 -579
  240. data/third_party/nanopb/pb_common.c +0 -97
  241. data/third_party/nanopb/pb_common.h +0 -42
  242. data/third_party/nanopb/pb_decode.c +0 -1347
  243. data/third_party/nanopb/pb_decode.h +0 -149
  244. data/third_party/nanopb/pb_encode.c +0 -696
  245. data/third_party/nanopb/pb_encode.h +0 -154
@@ -23,67 +23,105 @@
23
23
 
24
24
  #include <grpc/slice_buffer.h>
25
25
 
26
- #include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h"
27
26
  #include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h"
28
- #include "src/core/lib/iomgr/exec_ctx.h"
29
-
30
- #define XDS_SERVICE_NAME_MAX_LENGTH 128
31
-
32
- typedef grpc_lb_v1_Server_ip_address_t xds_grpclb_ip_address;
33
- typedef grpc_lb_v1_LoadBalanceRequest xds_grpclb_request;
34
- typedef grpc_lb_v1_InitialLoadBalanceResponse xds_grpclb_initial_response;
35
- typedef grpc_lb_v1_Server xds_grpclb_server;
36
- typedef google_protobuf_Duration xds_grpclb_duration;
37
- typedef google_protobuf_Timestamp xds_grpclb_timestamp;
38
-
39
- typedef struct {
40
- xds_grpclb_server** servers;
41
- size_t num_servers;
42
- } xds_grpclb_serverlist;
43
-
44
- /** Create a request for a gRPC LB service under \a lb_service_name */
45
- xds_grpclb_request* xds_grpclb_request_create(const char* lb_service_name);
46
- xds_grpclb_request* xds_grpclb_load_report_request_create_locked(
47
- grpc_core::XdsLbClientStats* client_stats);
48
-
49
- /** Protocol Buffers v3-encode \a request */
50
- grpc_slice xds_grpclb_request_encode(const xds_grpclb_request* request);
51
-
52
- /** Destroy \a request */
53
- void xds_grpclb_request_destroy(xds_grpclb_request* request);
54
-
55
- /** Parse (ie, decode) the bytes in \a encoded_xds_grpclb_response as a \a
56
- * xds_grpclb_initial_response */
57
- xds_grpclb_initial_response* xds_grpclb_initial_response_parse(
58
- const grpc_slice& encoded_xds_grpclb_response);
59
-
60
- /** Parse the list of servers from an encoded \a xds_grpclb_response */
61
- xds_grpclb_serverlist* xds_grpclb_response_parse_serverlist(
62
- const grpc_slice& encoded_xds_grpclb_response);
63
-
64
- /** Return a copy of \a sl. The caller is responsible for calling \a
65
- * xds_grpclb_destroy_serverlist on the returned copy. */
66
- xds_grpclb_serverlist* xds_grpclb_serverlist_copy(
67
- const xds_grpclb_serverlist* sl);
68
-
69
- bool xds_grpclb_serverlist_equals(const xds_grpclb_serverlist* lhs,
70
- const xds_grpclb_serverlist* rhs);
71
-
72
- bool xds_grpclb_server_equals(const xds_grpclb_server* lhs,
73
- const xds_grpclb_server* rhs);
74
-
75
- /** Destroy \a serverlist */
76
- void xds_grpclb_destroy_serverlist(xds_grpclb_serverlist* serverlist);
77
-
78
- /** Compare \a lhs against \a rhs and return 0 if \a lhs and \a rhs are equal,
79
- * < 0 if \a lhs represents a duration shorter than \a rhs and > 0 otherwise */
80
- int xds_grpclb_duration_compare(const xds_grpclb_duration* lhs,
81
- const xds_grpclb_duration* rhs);
82
-
83
- grpc_millis xds_grpclb_duration_to_millis(xds_grpclb_duration* duration_pb);
84
-
85
- /** Destroy \a initial_response */
86
- void xds_grpclb_initial_response_destroy(xds_grpclb_initial_response* response);
27
+ #include "src/core/ext/filters/client_channel/server_address.h"
28
+
29
+ namespace grpc_core {
30
+
31
+ struct XdsLocalityInfo {
32
+ bool operator==(const XdsLocalityInfo& other) const {
33
+ return *locality_name == *other.locality_name &&
34
+ serverlist == other.serverlist && lb_weight == other.lb_weight &&
35
+ priority == other.priority;
36
+ }
37
+
38
+ // This comparator only compares the locality names.
39
+ struct Less {
40
+ bool operator()(const XdsLocalityInfo& lhs,
41
+ const XdsLocalityInfo& rhs) const {
42
+ return XdsLocalityName::Less()(lhs.locality_name, rhs.locality_name);
43
+ }
44
+ };
45
+
46
+ RefCountedPtr<XdsLocalityName> locality_name;
47
+ ServerAddressList serverlist;
48
+ uint32_t lb_weight;
49
+ uint32_t priority;
50
+ };
51
+
52
+ using XdsLocalityList = InlinedVector<XdsLocalityInfo, 1>;
53
+
54
+ // There are two phases of accessing this class's content:
55
+ // 1. to initialize in the control plane combiner;
56
+ // 2. to use in the data plane combiner.
57
+ // So no additional synchronization is needed.
58
+ class XdsDropConfig : public RefCounted<XdsDropConfig> {
59
+ public:
60
+ struct DropCategory {
61
+ bool operator==(const DropCategory& other) const {
62
+ return strcmp(name.get(), other.name.get()) == 0 &&
63
+ parts_per_million == other.parts_per_million;
64
+ }
65
+
66
+ UniquePtr<char> name;
67
+ const uint32_t parts_per_million;
68
+ };
69
+
70
+ using DropCategoryList = InlinedVector<DropCategory, 2>;
71
+
72
+ void AddCategory(UniquePtr<char> name, uint32_t parts_per_million) {
73
+ drop_category_list_.emplace_back(
74
+ DropCategory{std::move(name), parts_per_million});
75
+ }
76
+
77
+ // The only method invoked from the data plane combiner.
78
+ bool ShouldDrop(const UniquePtr<char>** category_name) const;
79
+
80
+ const DropCategoryList& drop_category_list() const {
81
+ return drop_category_list_;
82
+ }
83
+
84
+ bool operator==(const XdsDropConfig& other) const {
85
+ return drop_category_list_ == other.drop_category_list_;
86
+ }
87
+ bool operator!=(const XdsDropConfig& other) const {
88
+ return !(*this == other);
89
+ }
90
+
91
+ private:
92
+ DropCategoryList drop_category_list_;
93
+ };
94
+
95
+ struct XdsUpdate {
96
+ XdsLocalityList locality_list;
97
+ RefCountedPtr<XdsDropConfig> drop_config;
98
+ bool drop_all = false;
99
+ };
100
+
101
+ // Creates an EDS request querying \a service_name.
102
+ grpc_slice XdsEdsRequestCreateAndEncode(const char* service_name);
103
+
104
+ // Parses the EDS response and returns the args to update locality map. If there
105
+ // is any error, the output update is invalid.
106
+ grpc_error* XdsEdsResponseDecodeAndParse(const grpc_slice& encoded_response,
107
+ XdsUpdate* update);
108
+
109
+ // Creates an LRS request querying \a server_name.
110
+ grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name);
111
+
112
+ // Creates an LRS request sending client-side load reports. If all the counters
113
+ // in \a client_stats are zero, returns empty slice.
114
+ grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
115
+ XdsClientStats* client_stats);
116
+
117
+ // Parses the LRS response and returns the client-side load reporting interval.
118
+ // If there is any error (e.g., the found server name doesn't match \a
119
+ // expected_server_name), the output config is invalid.
120
+ grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
121
+ grpc_millis* load_reporting_interval,
122
+ const char* expected_server_name);
123
+
124
+ } // namespace grpc_core
87
125
 
88
126
  #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_XDS_XDS_LOAD_BALANCER_API_H \
89
127
  */
@@ -117,8 +117,13 @@ namespace {
117
117
  grpc_json* ParseLoadBalancingConfigHelper(const grpc_json* lb_config_array,
118
118
  grpc_error** error) {
119
119
  GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
120
+ if (lb_config_array == nullptr) {
121
+ *error =
122
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("LB config JSON tree is null");
123
+ return nullptr;
124
+ }
120
125
  char* error_msg;
121
- if (lb_config_array == nullptr || lb_config_array->type != GRPC_JSON_ARRAY) {
126
+ if (lb_config_array->type != GRPC_JSON_ARRAY) {
122
127
  gpr_asprintf(&error_msg, "field:%s error:type should be array",
123
128
  lb_config_array->key);
124
129
  *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
@@ -0,0 +1,89 @@
1
+ /*
2
+ *
3
+ * Copyright 2019 gRPC authors.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ */
18
+
19
+ #include <grpc/support/port_platform.h>
20
+
21
+ #include "src/core/ext/filters/client_channel/resolver_registry.h"
22
+
23
+ namespace grpc_core {
24
+
25
+ namespace {
26
+
27
+ class XdsResolver : public Resolver {
28
+ public:
29
+ explicit XdsResolver(ResolverArgs args)
30
+ : Resolver(args.combiner, std::move(args.result_handler)),
31
+ args_(grpc_channel_args_copy(args.args)) {}
32
+ ~XdsResolver() override { grpc_channel_args_destroy(args_); }
33
+
34
+ void StartLocked() override;
35
+
36
+ void ShutdownLocked() override{};
37
+
38
+ private:
39
+ const grpc_channel_args* args_;
40
+ };
41
+
42
+ void XdsResolver::StartLocked() {
43
+ static const char* service_config =
44
+ "{\n"
45
+ " \"loadBalancingConfig\":[\n"
46
+ " { \"xds_experimental\":{} }\n"
47
+ " ]\n"
48
+ "}";
49
+ Result result;
50
+ result.args = args_;
51
+ args_ = nullptr;
52
+ grpc_error* error = GRPC_ERROR_NONE;
53
+ result.service_config = ServiceConfig::Create(service_config, &error);
54
+ result_handler()->ReturnResult(std::move(result));
55
+ }
56
+
57
+ //
58
+ // Factory
59
+ //
60
+
61
+ class XdsResolverFactory : public ResolverFactory {
62
+ public:
63
+ bool IsValidUri(const grpc_uri* uri) const override {
64
+ if (GPR_UNLIKELY(0 != strcmp(uri->authority, ""))) {
65
+ gpr_log(GPR_ERROR, "URI authority not supported");
66
+ return false;
67
+ }
68
+ return true;
69
+ }
70
+
71
+ OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
72
+ if (!IsValidUri(args.uri)) return nullptr;
73
+ return OrphanablePtr<Resolver>(New<XdsResolver>(std::move(args)));
74
+ }
75
+
76
+ const char* scheme() const override { return "xds-experimental"; }
77
+ };
78
+
79
+ } // namespace
80
+
81
+ } // namespace grpc_core
82
+
83
+ void grpc_resolver_xds_init() {
84
+ grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
85
+ grpc_core::UniquePtr<grpc_core::ResolverFactory>(
86
+ grpc_core::New<grpc_core::XdsResolverFactory>()));
87
+ }
88
+
89
+ void grpc_resolver_xds_shutdown() {}
@@ -113,13 +113,6 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
113
113
  return parent_->channel_control_helper()->CreateSubchannel(args);
114
114
  }
115
115
 
116
- grpc_channel* CreateChannel(const char* target,
117
- const grpc_channel_args& args) override {
118
- if (parent_->resolver_ == nullptr) return nullptr; // Shutting down.
119
- if (!CalledByCurrentChild() && !CalledByPendingChild()) return nullptr;
120
- return parent_->channel_control_helper()->CreateChannel(target, args);
121
- }
122
-
123
116
  void UpdateState(grpc_connectivity_state state,
124
117
  UniquePtr<SubchannelPicker> picker) override {
125
118
  if (parent_->resolver_ == nullptr) return; // Shutting down.
@@ -160,6 +153,8 @@ class ResolvingLoadBalancingPolicy::ResolvingControlHelper
160
153
  }
161
154
  }
162
155
 
156
+ void AddTraceEvent(TraceSeverity severity, StringView message) override {}
157
+
163
158
  void set_child(LoadBalancingPolicy* child) { child_ = child; }
164
159
 
165
160
  private:
@@ -433,7 +428,7 @@ void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
433
428
  size_t len = 0;
434
429
  UniquePtr<char> message(gpr_strvec_flatten(&v, &len));
435
430
  channel_control_helper()->AddTraceEvent(ChannelControlHelper::TRACE_INFO,
436
- message.get());
431
+ StringView(message.get()));
437
432
  gpr_strvec_destroy(&v);
438
433
  }
439
434
  }
@@ -20,8 +20,6 @@
20
20
 
21
21
  #include "src/core/ext/filters/client_channel/server_address.h"
22
22
 
23
- #include <string.h>
24
-
25
23
  namespace grpc_core {
26
24
 
27
25
  //
@@ -39,7 +37,7 @@ ServerAddress::ServerAddress(const void* address, size_t address_len,
39
37
  address_.len = static_cast<socklen_t>(address_len);
40
38
  }
41
39
 
42
- bool ServerAddress::operator==(const grpc_core::ServerAddress& other) const {
40
+ bool ServerAddress::operator==(const ServerAddress& other) const {
43
41
  return address_.len == other.address_.len &&
44
42
  memcmp(address_.addr, other.address_.addr, address_.len) == 0 &&
45
43
  grpc_channel_args_compare(args_, other.args_) == 0;
@@ -24,7 +24,6 @@
24
24
  #include "src/core/lib/channel/channel_args.h"
25
25
  #include "src/core/lib/gprpp/inlined_vector.h"
26
26
  #include "src/core/lib/iomgr/resolve_address.h"
27
- #include "src/core/lib/uri/uri_parser.h"
28
27
 
29
28
  // Channel arg key for a bool indicating whether an address is a grpclb
30
29
  // load balancer (as opposed to a backend).
@@ -68,6 +67,7 @@ class ServerAddress {
68
67
  }
69
68
  ServerAddress& operator=(ServerAddress&& other) {
70
69
  address_ = other.address_;
70
+ grpc_channel_args_destroy(args_);
71
71
  args_ = other.args_;
72
72
  other.args_ = nullptr;
73
73
  return *this;
@@ -26,6 +26,7 @@
26
26
  #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
27
27
  #include "src/core/lib/backoff/backoff.h"
28
28
  #include "src/core/lib/channel/channel_stack.h"
29
+ #include "src/core/lib/gpr/time_precise.h"
29
30
  #include "src/core/lib/gprpp/arena.h"
30
31
  #include "src/core/lib/gprpp/map.h"
31
32
  #include "src/core/lib/gprpp/ref_counted.h"
@@ -104,7 +105,7 @@ class SubchannelCall {
104
105
  RefCountedPtr<ConnectedSubchannel> connected_subchannel;
105
106
  grpc_polling_entity* pollent;
106
107
  grpc_slice path;
107
- gpr_timespec start_time;
108
+ gpr_cycle_counter start_time;
108
109
  grpc_millis deadline;
109
110
  Arena* arena;
110
111
  grpc_call_context_element* context;
@@ -27,12 +27,12 @@
27
27
  #include "src/core/lib/surface/channel_init.h"
28
28
  #include "src/core/lib/transport/http2_errors.h"
29
29
 
30
- // The idle filter is disabled in client channel by default.
31
- // To enable the idle filte, set GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS to [0, INT_MAX)
32
- // in channel args.
33
- // TODO(qianchengz): Find a reasonable default value. Maybe check what deault
34
- // value Java uses.
35
- #define DEFAULT_IDLE_TIMEOUT_MS INT_MAX
30
+ // The idle filter is enabled in client channel by default.
31
+ // Set GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS to [1000, INT_MAX) in channel args to
32
+ // configure the idle timeout.
33
+ #define DEFAULT_IDLE_TIMEOUT_MS (30 /*minutes*/ * 60 * 1000)
34
+ // The user input idle timeout smaller than this would be capped to it.
35
+ #define MIN_IDLE_TIMEOUT_MS (1 /*second*/ * 1000)
36
36
 
37
37
  namespace grpc_core {
38
38
 
@@ -47,10 +47,82 @@ TraceFlag grpc_trace_client_idle_filter(false, "client_idle_filter");
47
47
 
48
48
  namespace {
49
49
 
50
+ /*
51
+ client_idle_filter maintains a state tracking if there are active calls in the
52
+ channel and its internal idle_timer_. The states are specified as following:
53
+
54
+ +--------------------------------------------+-------------+---------+
55
+ | ChannelState | idle_timer_ | channel |
56
+ +--------------------------------------------+-------------+---------+
57
+ | IDLE | unset | idle |
58
+ | CALLS_ACTIVE | unset | busy |
59
+ | TIMER_PENDING | set-valid | idle |
60
+ | TIMER_PENDING_CALLS_ACTIVE | set-invalid | busy |
61
+ | TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START | set-invalid | idle |
62
+ +--------------------------------------------+-------------+---------+
63
+
64
+ IDLE: The initial state of the client_idle_filter, indicating the channel is
65
+ in IDLE.
66
+
67
+ CALLS_ACTIVE: The channel has 1 or 1+ active calls and the timer is not set.
68
+
69
+ TIMER_PENDING: The state after the timer is set and no calls have arrived
70
+ after the timer is set. The channel must have 0 active call in this state. If
71
+ the timer is fired in this state, the channel will go into IDLE state.
72
+
73
+ TIMER_PENDING_CALLS_ACTIVE: The state after the timer is set and at least one
74
+ call has arrived after the timer is set. The channel must have 1 or 1+ active
75
+ calls in this state. If the timer is fired in this state, we won't reschedule
76
+ it.
77
+
78
+ TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START: The state after the timer is set
79
+ and at least one call has arrived after the timer is set, BUT the channel
80
+ currently has 0 active call. If the timer is fired in this state, we will
81
+ reschedule it according to the finish time of the latest call.
82
+
83
+ PROCESSING: The state set to block other threads when the setting thread is
84
+ doing some work to keep state consistency.
85
+
86
+ idle_timer_ will not be cancelled (unless the channel is shutting down).
87
+ If the timer callback is called when the idle_timer_ is valid (i.e. idle_state
88
+ is TIMER_PENDING), the channel will enter IDLE, otherwise the channel won't be
89
+ changed.
90
+
91
+ State transitions:
92
+ IDLE
93
+ | ^
94
+ --------------------------------- *
95
+ | *
96
+ v *
97
+ CALLS_ACTIVE =================> TIMER_PENDING
98
+ ^ | ^
99
+ * ------------------------------ *
100
+ * | *
101
+ * v *
102
+ TIMER_PENDING_CALLS_ACTIVE ===> TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START
103
+ ^ |
104
+ | |
105
+ ---------------------------------
106
+
107
+ ---> Triggered by IncreaseCallCount()
108
+ ===> Triggered by DecreaseCallCount()
109
+ ***> Triggered by IdleTimerCallback()
110
+ */
111
+ enum ChannelState {
112
+ IDLE,
113
+ CALLS_ACTIVE,
114
+ TIMER_PENDING,
115
+ TIMER_PENDING_CALLS_ACTIVE,
116
+ TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START,
117
+ PROCESSING
118
+ };
119
+
50
120
  grpc_millis GetClientIdleTimeout(const grpc_channel_args* args) {
51
- return grpc_channel_arg_get_integer(
52
- grpc_channel_args_find(args, GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS),
53
- {DEFAULT_IDLE_TIMEOUT_MS, 0, INT_MAX});
121
+ return GPR_MAX(
122
+ grpc_channel_arg_get_integer(
123
+ grpc_channel_args_find(args, GRPC_ARG_CLIENT_IDLE_TIMEOUT_MS),
124
+ {DEFAULT_IDLE_TIMEOUT_MS, 0, INT_MAX}),
125
+ MIN_IDLE_TIMEOUT_MS);
54
126
  }
55
127
 
56
128
  class ChannelData {
@@ -86,8 +158,9 @@ class ChannelData {
86
158
  const grpc_millis client_idle_timeout_;
87
159
 
88
160
  // Member data used to track the state of channel.
89
- Mutex call_count_mu_;
90
- size_t call_count_;
161
+ grpc_millis last_idle_time_;
162
+ Atomic<intptr_t> call_count_{0};
163
+ Atomic<ChannelState> state_{IDLE};
91
164
 
92
165
  // Idle timer and its callback closure.
93
166
  grpc_timer idle_timer_;
@@ -115,37 +188,105 @@ void ChannelData::StartTransportOp(grpc_channel_element* elem,
115
188
  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
116
189
  // Catch the disconnect_with_error transport op.
117
190
  if (op->disconnect_with_error != nullptr) {
118
- // Disconnect. Cancel the timer if we set it before.
119
- // IncreaseCallCount() introduces a dummy call. It will cancel the timer and
120
- // prevent the timer from being reset by other threads.
191
+ // IncreaseCallCount() introduces a dummy call and prevent the timer from
192
+ // being reset by other threads.
121
193
  chand->IncreaseCallCount();
194
+ // If the timer has been set, cancel the timer.
195
+ // No synchronization issues here. grpc_timer_cancel() is valid as long as
196
+ // the timer has been init()ed before.
197
+ grpc_timer_cancel(&chand->idle_timer_);
122
198
  }
123
199
  // Pass the op to the next filter.
124
200
  grpc_channel_next_op(elem, op);
125
201
  }
126
202
 
127
203
  void ChannelData::IncreaseCallCount() {
128
- MutexLock lock(&call_count_mu_);
129
- if (call_count_++ == 0) {
130
- grpc_timer_cancel(&idle_timer_);
204
+ const intptr_t previous_value = call_count_.FetchAdd(1, MemoryOrder::RELAXED);
205
+ GRPC_IDLE_FILTER_LOG("call counter has increased to %" PRIuPTR,
206
+ previous_value + 1);
207
+ if (previous_value == 0) {
208
+ // This call is the one that makes the channel busy.
209
+ // Loop here to make sure the previous decrease operation has finished.
210
+ ChannelState state = state_.Load(MemoryOrder::RELAXED);
211
+ while (true) {
212
+ switch (state) {
213
+ // Timer has not been set. Switch to CALLS_ACTIVE.
214
+ case IDLE:
215
+ // In this case, no other threads will modify the state, so we can
216
+ // just store the value.
217
+ state_.Store(CALLS_ACTIVE, MemoryOrder::RELAXED);
218
+ return;
219
+ // Timer has been set. Switch to TIMER_PENDING_CALLS_ACTIVE.
220
+ case TIMER_PENDING:
221
+ case TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START:
222
+ // At this point, the state may have been switched to IDLE by the
223
+ // idle timer callback. Therefore, use CAS operation to change the
224
+ // state atomically.
225
+ // Use MemoryOrder::ACQUIRE on success to ensure last_idle_time_ has
226
+ // been properly set in DecreaseCallCount().
227
+ if (state_.CompareExchangeWeak(&state, TIMER_PENDING_CALLS_ACTIVE,
228
+ MemoryOrder::ACQUIRE,
229
+ MemoryOrder::RELAXED)) {
230
+ return;
231
+ }
232
+ break;
233
+ default:
234
+ // The state has not been switched to desired value yet, try again.
235
+ state = state_.Load(MemoryOrder::RELAXED);
236
+ break;
237
+ }
238
+ }
131
239
  }
132
- GRPC_IDLE_FILTER_LOG("call counter has increased to %" PRIuPTR, call_count_);
133
240
  }
134
241
 
135
242
  void ChannelData::DecreaseCallCount() {
136
- MutexLock lock(&call_count_mu_);
137
- if (call_count_-- == 1) {
138
- StartIdleTimer();
243
+ const intptr_t previous_value = call_count_.FetchSub(1, MemoryOrder::RELAXED);
244
+ GRPC_IDLE_FILTER_LOG("call counter has decreased to %" PRIuPTR,
245
+ previous_value - 1);
246
+ if (previous_value == 1) {
247
+ // This call is the one that makes the channel idle.
248
+ // last_idle_time_ does not need to be Atomic<> because busy-loops in
249
+ // IncreaseCallCount(), DecreaseCallCount() and IdleTimerCallback() will
250
+ // prevent multiple threads from simultaneously accessing this variable.
251
+ last_idle_time_ = ExecCtx::Get()->Now();
252
+ ChannelState state = state_.Load(MemoryOrder::RELAXED);
253
+ while (true) {
254
+ switch (state) {
255
+ // Timer has not been set. Set the timer and switch to TIMER_PENDING
256
+ case CALLS_ACTIVE:
257
+ // Release store here to make other threads see the updated value of
258
+ // last_idle_time_.
259
+ StartIdleTimer();
260
+ state_.Store(TIMER_PENDING, MemoryOrder::RELEASE);
261
+ return;
262
+ // Timer has been set. Switch to
263
+ // TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START
264
+ case TIMER_PENDING_CALLS_ACTIVE:
265
+ // At this point, the state may have been switched to CALLS_ACTIVE by
266
+ // the idle timer callback. Therefore, use CAS operation to change the
267
+ // state atomically.
268
+ // Release store here to make the idle timer callback see the updated
269
+ // value of last_idle_time_ to properly reset the idle timer.
270
+ if (state_.CompareExchangeWeak(
271
+ &state, TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START,
272
+ MemoryOrder::RELEASE, MemoryOrder::RELAXED)) {
273
+ return;
274
+ }
275
+ break;
276
+ default:
277
+ // The state has not been switched to desired value yet, try again.
278
+ state = state_.Load(MemoryOrder::RELAXED);
279
+ break;
280
+ }
281
+ }
139
282
  }
140
- GRPC_IDLE_FILTER_LOG("call counter has decreased to %" PRIuPTR, call_count_);
141
283
  }
142
284
 
143
285
  ChannelData::ChannelData(grpc_channel_element* elem,
144
286
  grpc_channel_element_args* args, grpc_error** error)
145
287
  : elem_(elem),
146
288
  channel_stack_(args->channel_stack),
147
- client_idle_timeout_(GetClientIdleTimeout(args->channel_args)),
148
- call_count_(0) {
289
+ client_idle_timeout_(GetClientIdleTimeout(args->channel_args)) {
149
290
  // If the idle filter is explicitly disabled in channel args, this ctor should
150
291
  // not get called.
151
292
  GPR_ASSERT(client_idle_timeout_ != GRPC_MILLIS_INF_FUTURE);
@@ -165,10 +306,45 @@ ChannelData::ChannelData(grpc_channel_element* elem,
165
306
  void ChannelData::IdleTimerCallback(void* arg, grpc_error* error) {
166
307
  GRPC_IDLE_FILTER_LOG("timer alarms");
167
308
  ChannelData* chand = static_cast<ChannelData*>(arg);
168
- {
169
- MutexLock lock(&chand->call_count_mu_);
170
- if (error == GRPC_ERROR_NONE && chand->call_count_ == 0) {
171
- chand->EnterIdle();
309
+ if (error != GRPC_ERROR_NONE) {
310
+ GRPC_IDLE_FILTER_LOG("timer canceled");
311
+ GRPC_CHANNEL_STACK_UNREF(chand->channel_stack_, "max idle timer callback");
312
+ return;
313
+ }
314
+ bool finished = false;
315
+ ChannelState state = chand->state_.Load(MemoryOrder::RELAXED);
316
+ while (!finished) {
317
+ switch (state) {
318
+ case TIMER_PENDING:
319
+ // Change the state to PROCESSING to block IncreaseCallCout() until the
320
+ // EnterIdle() operation finishes, preventing mistakenly entering IDLE
321
+ // when active RPC exists.
322
+ finished = chand->state_.CompareExchangeWeak(
323
+ &state, PROCESSING, MemoryOrder::ACQUIRE, MemoryOrder::RELAXED);
324
+ if (finished) {
325
+ chand->EnterIdle();
326
+ chand->state_.Store(IDLE, MemoryOrder::RELAXED);
327
+ }
328
+ break;
329
+ case TIMER_PENDING_CALLS_ACTIVE:
330
+ finished = chand->state_.CompareExchangeWeak(
331
+ &state, CALLS_ACTIVE, MemoryOrder::RELAXED, MemoryOrder::RELAXED);
332
+ break;
333
+ case TIMER_PENDING_CALLS_SEEN_SINCE_TIMER_START:
334
+ // Change the state to PROCESSING to block IncreaseCallCount() until the
335
+ // StartIdleTimer() operation finishes, preventing mistakenly restarting
336
+ // the timer after grpc_timer_cancel() when shutdown.
337
+ finished = chand->state_.CompareExchangeWeak(
338
+ &state, PROCESSING, MemoryOrder::ACQUIRE, MemoryOrder::RELAXED);
339
+ if (finished) {
340
+ chand->StartIdleTimer();
341
+ chand->state_.Store(TIMER_PENDING, MemoryOrder::RELAXED);
342
+ }
343
+ break;
344
+ default:
345
+ // The state has not been switched to desired value yet, try again.
346
+ state = chand->state_.Load(MemoryOrder::RELAXED);
347
+ break;
172
348
  }
173
349
  }
174
350
  GRPC_IDLE_FILTER_LOG("timer finishes");
@@ -185,7 +361,7 @@ void ChannelData::StartIdleTimer() {
185
361
  GRPC_IDLE_FILTER_LOG("timer has started");
186
362
  // Hold a ref to the channel stack for the timer callback.
187
363
  GRPC_CHANNEL_STACK_REF(channel_stack_, "max idle timer callback");
188
- grpc_timer_init(&idle_timer_, ExecCtx::Get()->Now() + client_idle_timeout_,
364
+ grpc_timer_init(&idle_timer_, last_idle_time_ + client_idle_timeout_,
189
365
  &idle_timer_callback_);
190
366
  }
191
367
 
@@ -193,6 +369,8 @@ void ChannelData::EnterIdle() {
193
369
  GRPC_IDLE_FILTER_LOG("the channel will enter IDLE");
194
370
  // Hold a ref to the channel stack for the transport op.
195
371
  GRPC_CHANNEL_STACK_REF(channel_stack_, "idle transport op");
372
+ // Initialize the transport op.
373
+ idle_transport_op_ = {};
196
374
  idle_transport_op_.disconnect_with_error = grpc_error_set_int(
197
375
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("enter idle"),
198
376
  GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, GRPC_CHANNEL_IDLE);