grpc 1.20.0 → 1.21.0

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

Potentially problematic release.


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

Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +500 -29
  3. data/etc/roots.pem +146 -0
  4. data/include/grpc/grpc_security.h +1 -1
  5. data/include/grpc/impl/codegen/grpc_types.h +10 -7
  6. data/include/grpc/impl/codegen/port_platform.h +11 -1
  7. data/include/grpc/impl/codegen/slice.h +1 -21
  8. data/include/grpc/impl/codegen/status.h +2 -1
  9. data/include/grpc/slice.h +1 -1
  10. data/src/core/ext/filters/client_channel/backup_poller.cc +19 -13
  11. data/src/core/ext/filters/client_channel/backup_poller.h +3 -0
  12. data/src/core/ext/filters/client_channel/channel_connectivity.cc +1 -1
  13. data/src/core/ext/filters/client_channel/client_channel.cc +2084 -1673
  14. data/src/core/ext/filters/client_channel/client_channel_channelz.cc +2 -3
  15. data/src/core/ext/filters/client_channel/client_channel_plugin.cc +4 -0
  16. data/src/core/ext/filters/client_channel/health/health_check_client.cc +54 -49
  17. data/src/core/ext/filters/client_channel/health/health_check_client.h +20 -9
  18. data/src/core/ext/filters/client_channel/http_connect_handshaker.cc +1 -2
  19. data/src/core/ext/filters/client_channel/http_connect_handshaker.h +1 -1
  20. data/src/core/ext/filters/client_channel/lb_policy.cc +3 -30
  21. data/src/core/ext/filters/client_channel/lb_policy.h +16 -25
  22. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +106 -81
  23. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +6 -2
  24. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +8 -12
  25. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +2 -2
  26. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +1 -1
  27. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +57 -49
  28. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +47 -41
  29. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +24 -20
  30. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +989 -284
  31. data/src/core/ext/filters/client_channel/lb_policy_factory.h +4 -1
  32. data/src/core/ext/filters/client_channel/lb_policy_registry.cc +105 -2
  33. data/src/core/ext/filters/client_channel/lb_policy_registry.h +9 -2
  34. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +79 -36
  35. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.cc +84 -2
  36. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +3 -0
  37. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +179 -0
  38. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +15 -3
  39. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +80 -4
  40. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +7 -13
  41. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +2 -2
  42. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +39 -0
  43. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +0 -6
  44. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +2 -64
  45. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.cc +28 -0
  46. data/src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h +29 -0
  47. data/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +4 -4
  48. data/src/core/ext/filters/client_channel/resolver_result_parsing.cc +367 -232
  49. data/src/core/ext/filters/client_channel/resolver_result_parsing.h +55 -76
  50. data/src/core/ext/filters/client_channel/resolving_lb_policy.cc +50 -39
  51. data/src/core/ext/filters/client_channel/resolving_lb_policy.h +18 -12
  52. data/src/core/ext/filters/client_channel/service_config.cc +247 -27
  53. data/src/core/ext/filters/client_channel/service_config.h +119 -166
  54. data/src/core/ext/filters/client_channel/subchannel.cc +46 -84
  55. data/src/core/ext/filters/client_channel/subchannel.h +7 -7
  56. data/src/core/ext/filters/deadline/deadline_filter.cc +3 -4
  57. data/src/core/ext/filters/deadline/deadline_filter.h +3 -2
  58. data/src/core/ext/filters/http/client/http_client_filter.cc +7 -5
  59. data/src/core/ext/filters/http/client/http_client_filter.h +1 -1
  60. data/src/core/ext/filters/http/client_authority_filter.cc +1 -1
  61. data/src/core/ext/filters/http/message_compress/message_compress_filter.cc +4 -3
  62. data/src/core/ext/filters/http/server/http_server_filter.cc +18 -12
  63. data/src/core/ext/filters/message_size/message_size_filter.cc +118 -76
  64. data/src/core/ext/filters/message_size/message_size_filter.h +33 -0
  65. data/src/core/ext/transport/chttp2/alpn/alpn.h +1 -1
  66. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +9 -7
  67. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +93 -60
  68. data/src/core/ext/transport/chttp2/transport/flow_control.h +1 -1
  69. data/src/core/ext/transport/chttp2/transport/frame_settings.cc +4 -3
  70. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +3 -3
  71. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +8 -2
  72. data/src/core/ext/transport/chttp2/transport/hpack_table.cc +2 -2
  73. data/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +1 -1
  74. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +3 -2
  75. data/src/core/ext/transport/chttp2/transport/internal.h +35 -23
  76. data/src/core/ext/transport/chttp2/transport/parsing.cc +4 -4
  77. data/src/core/ext/transport/chttp2/transport/stream_lists.cc +3 -3
  78. data/src/core/ext/transport/chttp2/transport/writing.cc +61 -27
  79. data/src/core/ext/transport/inproc/inproc_transport.cc +18 -18
  80. data/src/core/lib/channel/channel_args.cc +0 -101
  81. data/src/core/lib/channel/channel_args.h +0 -37
  82. data/src/core/lib/channel/channel_stack.h +9 -5
  83. data/src/core/lib/channel/channelz_registry.cc +1 -1
  84. data/src/core/lib/channel/connected_channel.cc +2 -2
  85. data/src/core/lib/channel/context.h +3 -0
  86. data/src/core/lib/channel/handshaker.cc +4 -4
  87. data/src/core/lib/channel/handshaker.h +1 -1
  88. data/src/core/lib/compression/compression_args.cc +127 -0
  89. data/src/core/lib/compression/compression_args.h +55 -0
  90. data/src/core/lib/debug/trace.cc +13 -7
  91. data/src/core/lib/debug/trace.h +12 -0
  92. data/src/core/lib/gpr/arena.h +13 -9
  93. data/src/core/lib/gpr/env.h +2 -5
  94. data/src/core/lib/gpr/env_linux.cc +6 -1
  95. data/src/core/lib/gpr/env_posix.cc +5 -0
  96. data/src/core/lib/gpr/env_windows.cc +7 -5
  97. data/src/core/lib/gpr/log.cc +9 -13
  98. data/src/core/lib/gpr/string.cc +12 -6
  99. data/src/core/lib/gpr/string.h +4 -2
  100. data/src/core/lib/gpr/time_posix.cc +13 -0
  101. data/src/core/lib/gprpp/arena.cc +103 -0
  102. data/src/core/lib/gprpp/arena.h +121 -0
  103. data/src/core/lib/gprpp/fork.cc +12 -29
  104. data/src/core/lib/gprpp/global_config.h +87 -0
  105. data/src/core/lib/gprpp/global_config_custom.h +29 -0
  106. data/src/core/lib/gprpp/global_config_env.cc +135 -0
  107. data/src/core/lib/gprpp/global_config_env.h +131 -0
  108. data/src/core/lib/gprpp/global_config_generic.h +44 -0
  109. data/src/core/lib/gprpp/map.h +419 -0
  110. data/src/core/lib/gprpp/optional.h +1 -0
  111. data/src/core/lib/gprpp/orphanable.h +2 -2
  112. data/src/core/lib/gprpp/{mutex_lock.h → pair.h} +15 -19
  113. data/src/core/lib/gprpp/ref_counted.h +18 -2
  114. data/src/core/lib/gprpp/sync.h +126 -0
  115. data/src/core/lib/http/parser.cc +1 -1
  116. data/src/core/lib/iomgr/call_combiner.cc +84 -90
  117. data/src/core/lib/iomgr/call_combiner.h +75 -82
  118. data/src/core/lib/iomgr/cfstream_handle.cc +202 -0
  119. data/src/core/lib/iomgr/cfstream_handle.h +82 -0
  120. data/src/core/lib/iomgr/combiner.h +1 -1
  121. data/src/core/lib/iomgr/endpoint_cfstream.cc +375 -0
  122. data/src/core/lib/iomgr/endpoint_cfstream.h +49 -0
  123. data/src/core/lib/iomgr/endpoint_pair_windows.cc +2 -2
  124. data/src/core/lib/iomgr/error.h +23 -0
  125. data/src/core/lib/iomgr/error_cfstream.cc +52 -0
  126. data/src/core/lib/iomgr/error_cfstream.h +31 -0
  127. data/src/core/lib/iomgr/ev_epoll1_linux.cc +34 -27
  128. data/src/core/lib/iomgr/ev_epollex_linux.cc +33 -33
  129. data/src/core/lib/iomgr/ev_poll_posix.cc +7 -7
  130. data/src/core/lib/iomgr/ev_posix.cc +15 -13
  131. data/src/core/lib/iomgr/ev_posix.h +4 -1
  132. data/src/core/lib/iomgr/executor.cc +13 -9
  133. data/src/core/lib/iomgr/fork_posix.cc +0 -1
  134. data/src/core/lib/iomgr/internal_errqueue.cc +1 -1
  135. data/src/core/lib/iomgr/iomgr.cc +6 -5
  136. data/src/core/lib/iomgr/iomgr_custom.cc +3 -0
  137. data/src/core/lib/iomgr/iomgr_custom.h +2 -0
  138. data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +93 -0
  139. data/src/core/lib/iomgr/iomgr_windows.cc +1 -0
  140. data/src/core/lib/iomgr/lockfree_event.cc +3 -3
  141. data/src/core/lib/iomgr/port.h +11 -0
  142. data/src/core/lib/iomgr/resource_quota.cc +40 -37
  143. data/src/core/lib/iomgr/socket_utils_common_posix.cc +6 -2
  144. data/src/core/lib/iomgr/socket_windows.cc +19 -0
  145. data/src/core/lib/iomgr/socket_windows.h +8 -0
  146. data/src/core/lib/iomgr/tcp_client_cfstream.cc +216 -0
  147. data/src/core/lib/iomgr/tcp_client_custom.cc +2 -2
  148. data/src/core/lib/iomgr/tcp_client_posix.cc +3 -3
  149. data/src/core/lib/iomgr/tcp_client_windows.cc +1 -1
  150. data/src/core/lib/iomgr/tcp_custom.cc +9 -9
  151. data/src/core/lib/iomgr/tcp_posix.cc +41 -41
  152. data/src/core/lib/iomgr/tcp_server_custom.cc +3 -3
  153. data/src/core/lib/iomgr/tcp_server_posix.cc +14 -1
  154. data/src/core/lib/iomgr/tcp_server_windows.cc +2 -2
  155. data/src/core/lib/iomgr/tcp_windows.cc +7 -9
  156. data/src/core/lib/iomgr/timer_generic.cc +16 -16
  157. data/src/core/lib/iomgr/timer_manager.cc +12 -11
  158. data/src/core/lib/profiling/basic_timers.cc +10 -4
  159. data/src/core/lib/security/context/security_context.cc +6 -7
  160. data/src/core/lib/security/context/security_context.h +3 -4
  161. data/src/core/lib/security/credentials/jwt/jwt_credentials.cc +1 -1
  162. data/src/core/lib/security/credentials/jwt/jwt_verifier.cc +2 -3
  163. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  164. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +7 -7
  165. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +7 -5
  166. data/src/core/lib/security/security_connector/security_connector.cc +0 -1
  167. data/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +3 -2
  168. data/src/core/lib/security/security_connector/ssl_utils.cc +30 -26
  169. data/src/core/lib/security/security_connector/ssl_utils.h +5 -1
  170. data/src/core/lib/security/transport/client_auth_filter.cc +7 -11
  171. data/src/core/lib/security/transport/secure_endpoint.cc +4 -4
  172. data/src/core/lib/security/transport/server_auth_filter.cc +2 -3
  173. data/src/core/lib/slice/slice.cc +99 -116
  174. data/src/core/lib/slice/slice_buffer.cc +5 -0
  175. data/src/core/lib/slice/slice_intern.cc +38 -95
  176. data/src/core/lib/slice/slice_internal.h +200 -2
  177. data/src/core/lib/surface/api_trace.h +1 -1
  178. data/src/core/lib/surface/call.cc +41 -35
  179. data/src/core/lib/surface/call.h +7 -2
  180. data/src/core/lib/surface/call_details.cc +0 -1
  181. data/src/core/lib/surface/completion_queue.cc +36 -27
  182. data/src/core/lib/surface/init.cc +3 -4
  183. data/src/core/lib/surface/lame_client.cc +1 -1
  184. data/src/core/lib/surface/server.cc +18 -25
  185. data/src/core/lib/surface/version.cc +1 -1
  186. data/src/core/lib/transport/bdp_estimator.cc +3 -3
  187. data/src/core/lib/transport/bdp_estimator.h +2 -2
  188. data/src/core/lib/transport/connectivity_state.cc +10 -40
  189. data/src/core/lib/transport/connectivity_state.h +0 -8
  190. data/src/core/lib/transport/error_utils.cc +12 -0
  191. data/src/core/lib/transport/metadata.cc +206 -278
  192. data/src/core/lib/transport/metadata.h +205 -10
  193. data/src/core/lib/transport/static_metadata.cc +108 -116
  194. data/src/core/lib/transport/static_metadata.h +1 -2
  195. data/src/core/lib/transport/status_metadata.cc +3 -3
  196. data/src/core/lib/transport/transport.cc +29 -66
  197. data/src/core/lib/transport/transport.h +36 -8
  198. data/src/core/lib/transport/transport_impl.h +1 -1
  199. data/src/core/tsi/fake_transport_security.cc +4 -4
  200. data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +1 -1
  201. data/src/core/tsi/ssl_transport_security.cc +1 -1
  202. data/src/ruby/ext/grpc/rb_grpc.c +1 -1
  203. data/src/ruby/lib/grpc/errors.rb +22 -3
  204. data/src/ruby/lib/grpc/generic/bidi_call.rb +1 -1
  205. data/src/ruby/lib/grpc/generic/rpc_server.rb +1 -1
  206. data/src/ruby/lib/grpc/version.rb +1 -1
  207. data/src/ruby/spec/errors_spec.rb +141 -0
  208. metadata +57 -33
  209. data/src/core/lib/gpr/arena.cc +0 -192
@@ -33,7 +33,7 @@
33
33
  #include "src/core/lib/debug/stats.h"
34
34
  #include "src/core/lib/debug/trace.h"
35
35
  #include "src/core/lib/gprpp/fork.h"
36
- #include "src/core/lib/gprpp/mutex_lock.h"
36
+ #include "src/core/lib/gprpp/sync.h"
37
37
  #include "src/core/lib/http/parser.h"
38
38
  #include "src/core/lib/iomgr/call_combiner.h"
39
39
  #include "src/core/lib/iomgr/combiner.h"
@@ -73,6 +73,7 @@ static void do_basic_init(void) {
73
73
  g_shutting_down = false;
74
74
  grpc_register_built_in_plugins();
75
75
  grpc_cq_global_init();
76
+ gpr_time_init();
76
77
  g_initializations = 0;
77
78
  }
78
79
 
@@ -132,8 +133,6 @@ void grpc_init(void) {
132
133
  }
133
134
  grpc_core::Fork::GlobalInit();
134
135
  grpc_fork_handlers_auto_register();
135
- gpr_time_init();
136
- gpr_arena_init();
137
136
  grpc_stats_init();
138
137
  grpc_slice_intern_init();
139
138
  grpc_mdctx_global_init();
@@ -155,7 +154,7 @@ void grpc_init(void) {
155
154
  * at the appropriate time */
156
155
  grpc_register_security_filters();
157
156
  register_builtin_channel_init();
158
- grpc_tracer_init("GRPC_TRACE");
157
+ grpc_tracer_init();
159
158
  /* no more changes to channel init pipelines */
160
159
  grpc_channel_init_finalize();
161
160
  grpc_iomgr_start();
@@ -39,7 +39,7 @@ namespace grpc_core {
39
39
  namespace {
40
40
 
41
41
  struct CallData {
42
- grpc_call_combiner* call_combiner;
42
+ grpc_core::CallCombiner* call_combiner;
43
43
  grpc_linked_mdelem status;
44
44
  grpc_linked_mdelem details;
45
45
  grpc_core::Atomic<bool> filled_metadata;
@@ -123,7 +123,7 @@ typedef struct shutdown_tag {
123
123
  typedef enum {
124
124
  /* waiting for metadata */
125
125
  NOT_STARTED,
126
- /* inital metadata read, not flow controlled in yet */
126
+ /* initial metadata read, not flow controlled in yet */
127
127
  PENDING,
128
128
  /* flow controlled in, on completion queue */
129
129
  ACTIVATED,
@@ -190,7 +190,7 @@ struct call_data {
190
190
  grpc_closure publish;
191
191
 
192
192
  call_data* pending_next = nullptr;
193
- grpc_call_combiner* call_combiner;
193
+ grpc_core::CallCombiner* call_combiner;
194
194
  };
195
195
 
196
196
  struct request_matcher {
@@ -347,8 +347,8 @@ static void channel_broadcaster_shutdown(channel_broadcaster* cb,
347
347
  */
348
348
 
349
349
  static void request_matcher_init(request_matcher* rm, grpc_server* server) {
350
- memset(rm, 0, sizeof(*rm));
351
350
  rm->server = server;
351
+ rm->pending_head = rm->pending_tail = nullptr;
352
352
  rm->requests_per_cq = static_cast<gpr_locked_mpscq*>(
353
353
  gpr_malloc(sizeof(*rm->requests_per_cq) * server->cq_count));
354
354
  for (size_t i = 0; i < server->cq_count; i++) {
@@ -464,7 +464,8 @@ static void destroy_channel(channel_data* chand, grpc_error* error) {
464
464
  GRPC_CLOSURE_INIT(&chand->finish_destroy_channel_closure,
465
465
  finish_destroy_channel, chand, grpc_schedule_on_exec_ctx);
466
466
 
467
- if (grpc_server_channel_trace.enabled() && error != GRPC_ERROR_NONE) {
467
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_server_channel_trace) &&
468
+ error != GRPC_ERROR_NONE) {
468
469
  const char* msg = grpc_error_string(error);
469
470
  gpr_log(GPR_INFO, "Disconnected client: %s", msg);
470
471
  }
@@ -601,8 +602,9 @@ static void finish_start_new_rpc(
601
602
  break;
602
603
  case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: {
603
604
  grpc_op op;
604
- memset(&op, 0, sizeof(op));
605
605
  op.op = GRPC_OP_RECV_MESSAGE;
606
+ op.flags = 0;
607
+ op.reserved = nullptr;
606
608
  op.data.recv_message.recv_message = &calld->payload;
607
609
  GRPC_CLOSURE_INIT(&calld->publish, publish_new_rpc, elem,
608
610
  grpc_schedule_on_exec_ctx);
@@ -1098,20 +1100,6 @@ void* grpc_server_register_method(
1098
1100
  return m;
1099
1101
  }
1100
1102
 
1101
- static void start_listeners(void* s, grpc_error* error) {
1102
- grpc_server* server = static_cast<grpc_server*>(s);
1103
- for (listener* l = server->listeners; l; l = l->next) {
1104
- l->start(server, l->arg, server->pollsets, server->pollset_count);
1105
- }
1106
-
1107
- gpr_mu_lock(&server->mu_global);
1108
- server->starting = false;
1109
- gpr_cv_signal(&server->starting_cv);
1110
- gpr_mu_unlock(&server->mu_global);
1111
-
1112
- server_unref(server);
1113
- }
1114
-
1115
1103
  void grpc_server_start(grpc_server* server) {
1116
1104
  size_t i;
1117
1105
  grpc_core::ExecCtx exec_ctx;
@@ -1133,13 +1121,18 @@ void grpc_server_start(grpc_server* server) {
1133
1121
  request_matcher_init(&rm->matcher, server);
1134
1122
  }
1135
1123
 
1136
- server_ref(server);
1124
+ gpr_mu_lock(&server->mu_global);
1137
1125
  server->starting = true;
1138
- GRPC_CLOSURE_SCHED(
1139
- GRPC_CLOSURE_CREATE(
1140
- start_listeners, server,
1141
- grpc_core::Executor::Scheduler(grpc_core::ExecutorJobType::SHORT)),
1142
- GRPC_ERROR_NONE);
1126
+ gpr_mu_unlock(&server->mu_global);
1127
+
1128
+ for (listener* l = server->listeners; l; l = l->next) {
1129
+ l->start(server, l->arg, server->pollsets, server->pollset_count);
1130
+ }
1131
+
1132
+ gpr_mu_lock(&server->mu_global);
1133
+ server->starting = false;
1134
+ gpr_cv_signal(&server->starting_cv);
1135
+ gpr_mu_unlock(&server->mu_global);
1143
1136
  }
1144
1137
 
1145
1138
  void grpc_server_get_pollsets(grpc_server* server, grpc_pollset*** pollsets,
@@ -25,4 +25,4 @@
25
25
 
26
26
  const char* grpc_version_string(void) { return "7.0.0"; }
27
27
 
28
- const char* grpc_g_stands_for(void) { return "godric"; }
28
+ const char* grpc_g_stands_for(void) { return "gandalf"; }
@@ -46,7 +46,7 @@ grpc_millis BdpEstimator::CompletePing() {
46
46
  1e-9 * static_cast<double>(dt_ts.tv_nsec);
47
47
  double bw = dt > 0 ? (static_cast<double>(accumulator_) / dt) : 0;
48
48
  int start_inter_ping_delay = inter_ping_delay_;
49
- if (grpc_bdp_estimator_trace.enabled()) {
49
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
50
50
  gpr_log(GPR_INFO,
51
51
  "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64
52
52
  " dt=%lf bw=%lfMbs bw_est=%lfMbs",
@@ -57,7 +57,7 @@ grpc_millis BdpEstimator::CompletePing() {
57
57
  if (accumulator_ > 2 * estimate_ / 3 && bw > bw_est_) {
58
58
  estimate_ = GPR_MAX(accumulator_, estimate_ * 2);
59
59
  bw_est_ = bw;
60
- if (grpc_bdp_estimator_trace.enabled()) {
60
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
61
61
  gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64, name_,
62
62
  estimate_);
63
63
  }
@@ -74,7 +74,7 @@ grpc_millis BdpEstimator::CompletePing() {
74
74
  }
75
75
  if (start_inter_ping_delay != inter_ping_delay_) {
76
76
  stable_estimate_count_ = 0;
77
- if (grpc_bdp_estimator_trace.enabled()) {
77
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
78
78
  gpr_log(GPR_INFO, "bdp[%s]:update_inter_time to %dms", name_,
79
79
  inter_ping_delay_);
80
80
  }
@@ -49,7 +49,7 @@ class BdpEstimator {
49
49
  // grpc_bdp_estimator_add_incoming_bytes once a ping has been scheduled by a
50
50
  // transport (but not necessarily started)
51
51
  void SchedulePing() {
52
- if (grpc_bdp_estimator_trace.enabled()) {
52
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
53
53
  gpr_log(GPR_INFO, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
54
54
  accumulator_, estimate_);
55
55
  }
@@ -62,7 +62,7 @@ class BdpEstimator {
62
62
  // once
63
63
  // the ping is on the wire
64
64
  void StartPing() {
65
- if (grpc_bdp_estimator_trace.enabled()) {
65
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_bdp_estimator_trace)) {
66
66
  gpr_log(GPR_INFO, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
67
67
  accumulator_, estimate_);
68
68
  }
@@ -48,7 +48,6 @@ void grpc_connectivity_state_init(grpc_connectivity_state_tracker* tracker,
48
48
  grpc_connectivity_state init_state,
49
49
  const char* name) {
50
50
  gpr_atm_no_barrier_store(&tracker->current_state_atm, init_state);
51
- tracker->current_error = GRPC_ERROR_NONE;
52
51
  tracker->watchers = nullptr;
53
52
  tracker->name = gpr_strdup(name);
54
53
  }
@@ -69,7 +68,6 @@ void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker* tracker) {
69
68
  GRPC_CLOSURE_SCHED(w->notify, error);
70
69
  gpr_free(w);
71
70
  }
72
- GRPC_ERROR_UNREF(tracker->current_error);
73
71
  gpr_free(tracker->name);
74
72
  }
75
73
 
@@ -77,27 +75,13 @@ grpc_connectivity_state grpc_connectivity_state_check(
77
75
  grpc_connectivity_state_tracker* tracker) {
78
76
  grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
79
77
  gpr_atm_no_barrier_load(&tracker->current_state_atm));
80
- if (grpc_connectivity_state_trace.enabled()) {
78
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
81
79
  gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
82
80
  grpc_connectivity_state_name(cur));
83
81
  }
84
82
  return cur;
85
83
  }
86
84
 
87
- grpc_connectivity_state grpc_connectivity_state_get(
88
- grpc_connectivity_state_tracker* tracker, grpc_error** error) {
89
- grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
90
- gpr_atm_no_barrier_load(&tracker->current_state_atm));
91
- if (grpc_connectivity_state_trace.enabled()) {
92
- gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
93
- grpc_connectivity_state_name(cur));
94
- }
95
- if (error != nullptr) {
96
- *error = GRPC_ERROR_REF(tracker->current_error);
97
- }
98
- return cur;
99
- }
100
-
101
85
  bool grpc_connectivity_state_has_watchers(
102
86
  grpc_connectivity_state_tracker* connectivity_state) {
103
87
  return connectivity_state->watchers != nullptr;
@@ -108,7 +92,7 @@ bool grpc_connectivity_state_notify_on_state_change(
108
92
  grpc_closure* notify) {
109
93
  grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
110
94
  gpr_atm_no_barrier_load(&tracker->current_state_atm));
111
- if (grpc_connectivity_state_trace.enabled()) {
95
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
112
96
  if (current == nullptr) {
113
97
  gpr_log(GPR_INFO, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
114
98
  tracker->name, notify);
@@ -140,7 +124,7 @@ bool grpc_connectivity_state_notify_on_state_change(
140
124
  } else {
141
125
  if (cur != *current) {
142
126
  *current = cur;
143
- GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_REF(tracker->current_error));
127
+ GRPC_CLOSURE_SCHED(notify, GRPC_ERROR_NONE);
144
128
  } else {
145
129
  grpc_connectivity_state_watcher* w =
146
130
  static_cast<grpc_connectivity_state_watcher*>(gpr_malloc(sizeof(*w)));
@@ -155,29 +139,15 @@ bool grpc_connectivity_state_notify_on_state_change(
155
139
 
156
140
  void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
157
141
  grpc_connectivity_state state,
158
- grpc_error* error, const char* reason) {
142
+ const char* reason) {
159
143
  grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
160
144
  gpr_atm_no_barrier_load(&tracker->current_state_atm));
161
145
  grpc_connectivity_state_watcher* w;
162
- if (grpc_connectivity_state_trace.enabled()) {
163
- const char* error_string = grpc_error_string(error);
164
- gpr_log(GPR_INFO, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
165
- tracker->name, grpc_connectivity_state_name(cur),
166
- grpc_connectivity_state_name(state), reason, error, error_string);
167
- }
168
- switch (state) {
169
- case GRPC_CHANNEL_CONNECTING:
170
- case GRPC_CHANNEL_IDLE:
171
- case GRPC_CHANNEL_READY:
172
- GPR_ASSERT(error == GRPC_ERROR_NONE);
173
- break;
174
- case GRPC_CHANNEL_SHUTDOWN:
175
- case GRPC_CHANNEL_TRANSIENT_FAILURE:
176
- GPR_ASSERT(error != GRPC_ERROR_NONE);
177
- break;
146
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
147
+ gpr_log(GPR_INFO, "SET: %p %s: %s --> %s [%s]", tracker, tracker->name,
148
+ grpc_connectivity_state_name(cur),
149
+ grpc_connectivity_state_name(state), reason);
178
150
  }
179
- GRPC_ERROR_UNREF(tracker->current_error);
180
- tracker->current_error = error;
181
151
  if (cur == state) {
182
152
  return;
183
153
  }
@@ -186,10 +156,10 @@ void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
186
156
  while ((w = tracker->watchers) != nullptr) {
187
157
  *w->current = state;
188
158
  tracker->watchers = w->next;
189
- if (grpc_connectivity_state_trace.enabled()) {
159
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) {
190
160
  gpr_log(GPR_INFO, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify);
191
161
  }
192
- GRPC_CLOSURE_SCHED(w->notify, GRPC_ERROR_REF(tracker->current_error));
162
+ GRPC_CLOSURE_SCHED(w->notify, GRPC_ERROR_NONE);
193
163
  gpr_free(w);
194
164
  }
195
165
  }
@@ -37,8 +37,6 @@ typedef struct grpc_connectivity_state_watcher {
37
37
  typedef struct {
38
38
  /** current grpc_connectivity_state */
39
39
  gpr_atm current_state_atm;
40
- /** error associated with state */
41
- grpc_error* current_error;
42
40
  /** all our watchers */
43
41
  grpc_connectivity_state_watcher* watchers;
44
42
  /** a name to help debugging */
@@ -59,7 +57,6 @@ void grpc_connectivity_state_destroy(grpc_connectivity_state_tracker* tracker);
59
57
  * external lock */
60
58
  void grpc_connectivity_state_set(grpc_connectivity_state_tracker* tracker,
61
59
  grpc_connectivity_state state,
62
- grpc_error* associated_error,
63
60
  const char* reason);
64
61
 
65
62
  /** Return true if this connectivity state has watchers.
@@ -71,11 +68,6 @@ bool grpc_connectivity_state_has_watchers(
71
68
  grpc_connectivity_state grpc_connectivity_state_check(
72
69
  grpc_connectivity_state_tracker* tracker);
73
70
 
74
- /** Return the last seen connectivity state, and the associated error.
75
- Access must be serialized with an external lock. */
76
- grpc_connectivity_state grpc_connectivity_state_get(
77
- grpc_connectivity_state_tracker* tracker, grpc_error** error);
78
-
79
71
  /** Return 1 if the channel should start connecting, 0 otherwise.
80
72
  If current==NULL cancel notify if it is already queued (success==0 in that
81
73
  case).
@@ -48,6 +48,18 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline,
48
48
  grpc_status_code* code, grpc_slice* slice,
49
49
  grpc_http2_error_code* http_error,
50
50
  const char** error_string) {
51
+ // Fast path: We expect no error.
52
+ if (GPR_LIKELY(error == GRPC_ERROR_NONE)) {
53
+ if (code != nullptr) *code = GRPC_STATUS_OK;
54
+ if (slice != nullptr) {
55
+ grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, slice);
56
+ }
57
+ if (http_error != nullptr) {
58
+ *http_error = GRPC_HTTP2_NO_ERROR;
59
+ }
60
+ return;
61
+ }
62
+
51
63
  // Start with the parent error and recurse through the tree of children
52
64
  // until we find the first one that has a status code.
53
65
  grpc_error* found_error =
@@ -41,6 +41,10 @@
41
41
  #include "src/core/lib/slice/slice_string_helpers.h"
42
42
  #include "src/core/lib/transport/static_metadata.h"
43
43
 
44
+ using grpc_core::AllocatedMetadata;
45
+ using grpc_core::InternedMetadata;
46
+ using grpc_core::UserData;
47
+
44
48
  /* There are two kinds of mdelem and mdstr instances.
45
49
  * Static instances are declared in static_metadata.{h,c} and
46
50
  * are initialized by grpc_mdctx_global_init().
@@ -54,13 +58,40 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_metadata(false, "metadata");
54
58
 
55
59
  #ifndef NDEBUG
56
60
  #define DEBUG_ARGS , const char *file, int line
57
- #define FWD_DEBUG_ARGS , file, line
58
- #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s), __FILE__, __LINE__)
59
- #else
61
+ #define FWD_DEBUG_ARGS file, line
62
+
63
+ void grpc_mdelem_trace_ref(void* md, const grpc_slice& key,
64
+ const grpc_slice& value, intptr_t refcnt,
65
+ const char* file, int line) {
66
+ if (grpc_trace_metadata.enabled()) {
67
+ char* key_str = grpc_slice_to_c_string(key);
68
+ char* value_str = grpc_slice_to_c_string(value);
69
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
70
+ "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md, refcnt,
71
+ refcnt + 1, key_str, value_str);
72
+ gpr_free(key_str);
73
+ gpr_free(value_str);
74
+ }
75
+ }
76
+
77
+ void grpc_mdelem_trace_unref(void* md, const grpc_slice& key,
78
+ const grpc_slice& value, intptr_t refcnt,
79
+ const char* file, int line) {
80
+ if (grpc_trace_metadata.enabled()) {
81
+ char* key_str = grpc_slice_to_c_string(key);
82
+ char* value_str = grpc_slice_to_c_string(value);
83
+ gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
84
+ "ELM UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md,
85
+ refcnt, refcnt - 1, key_str, value_str);
86
+ gpr_free(key_str);
87
+ gpr_free(value_str);
88
+ }
89
+ }
90
+
91
+ #else // ifndef NDEBUG
60
92
  #define DEBUG_ARGS
61
93
  #define FWD_DEBUG_ARGS
62
- #define REF_MD_LOCKED(shard, s) ref_md_locked((shard), (s))
63
- #endif
94
+ #endif // ifndef NDEBUG
64
95
 
65
96
  #define INITIAL_SHARD_CAPACITY 8
66
97
  #define LOG2_SHARD_COUNT 4
@@ -69,43 +100,87 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_metadata(false, "metadata");
69
100
  #define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity))
70
101
  #define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1))
71
102
 
72
- typedef void (*destroy_user_data_func)(void* user_data);
73
-
74
- struct UserData {
75
- gpr_mu mu_user_data;
76
- gpr_atm destroy_user_data;
77
- gpr_atm user_data;
78
- };
79
-
80
- /* Shadow structure for grpc_mdelem_data for interned elements */
81
- typedef struct interned_metadata {
82
- /* must be byte compatible with grpc_mdelem_data */
83
- grpc_slice key;
84
- grpc_slice value;
85
-
86
- /* private only data */
87
- gpr_atm refcnt;
88
-
89
- UserData user_data;
103
+ AllocatedMetadata::AllocatedMetadata(const grpc_slice& key,
104
+ const grpc_slice& value)
105
+ : key_(grpc_slice_ref_internal(key)),
106
+ value_(grpc_slice_ref_internal(value)),
107
+ refcnt_(1) {
108
+ #ifndef NDEBUG
109
+ if (grpc_trace_metadata.enabled()) {
110
+ char* key_str = grpc_slice_to_c_string(key_);
111
+ char* value_str = grpc_slice_to_c_string(value_);
112
+ gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%" PRIdPTR ": '%s' = '%s'", this,
113
+ RefValue(), key_str, value_str);
114
+ gpr_free(key_str);
115
+ gpr_free(value_str);
116
+ }
117
+ #endif
118
+ }
90
119
 
91
- struct interned_metadata* bucket_next;
92
- } interned_metadata;
120
+ AllocatedMetadata::~AllocatedMetadata() {
121
+ grpc_slice_unref_internal(key_);
122
+ grpc_slice_unref_internal(value_);
123
+ void* user_data = user_data_.data.Load(grpc_core::MemoryOrder::RELAXED);
124
+ if (user_data) {
125
+ destroy_user_data_func destroy_user_data =
126
+ user_data_.destroy_user_data.Load(grpc_core::MemoryOrder::RELAXED);
127
+ destroy_user_data(user_data);
128
+ }
129
+ }
93
130
 
94
- /* Shadow structure for grpc_mdelem_data for allocated elements */
95
- typedef struct allocated_metadata {
96
- /* must be byte compatible with grpc_mdelem_data */
97
- grpc_slice key;
98
- grpc_slice value;
131
+ InternedMetadata::InternedMetadata(const grpc_slice& key,
132
+ const grpc_slice& value, uint32_t hash,
133
+ InternedMetadata* next)
134
+ : key_(grpc_slice_ref_internal(key)),
135
+ value_(grpc_slice_ref_internal(value)),
136
+ refcnt_(1),
137
+ hash_(hash),
138
+ link_(next) {
139
+ #ifndef NDEBUG
140
+ if (grpc_trace_metadata.enabled()) {
141
+ char* key_str = grpc_slice_to_c_string(key_);
142
+ char* value_str = grpc_slice_to_c_string(value_);
143
+ gpr_log(GPR_DEBUG, "ELM NEW:%p:%" PRIdPTR ": '%s' = '%s'", this,
144
+ RefValue(), key_str, value_str);
145
+ gpr_free(key_str);
146
+ gpr_free(value_str);
147
+ }
148
+ #endif
149
+ }
99
150
 
100
- /* private only data */
101
- gpr_atm refcnt;
151
+ InternedMetadata::~InternedMetadata() {
152
+ grpc_slice_unref_internal(key_);
153
+ grpc_slice_unref_internal(value_);
154
+ void* user_data = user_data_.data.Load(grpc_core::MemoryOrder::RELAXED);
155
+ if (user_data) {
156
+ destroy_user_data_func destroy_user_data =
157
+ user_data_.destroy_user_data.Load(grpc_core::MemoryOrder::RELAXED);
158
+ destroy_user_data(user_data);
159
+ }
160
+ }
102
161
 
103
- UserData user_data;
104
- } allocated_metadata;
162
+ size_t InternedMetadata::CleanupLinkedMetadata(
163
+ InternedMetadata::BucketLink* head) {
164
+ size_t num_freed = 0;
165
+ InternedMetadata::BucketLink* prev_next = head;
166
+ InternedMetadata *md, *next;
167
+
168
+ for (md = head->next; md; md = next) {
169
+ next = md->link_.next;
170
+ if (md->AllRefsDropped()) {
171
+ prev_next->next = next;
172
+ grpc_core::Delete(md);
173
+ num_freed++;
174
+ } else {
175
+ prev_next = &md->link_;
176
+ }
177
+ }
178
+ return num_freed;
179
+ }
105
180
 
106
181
  typedef struct mdtab_shard {
107
182
  gpr_mu mu;
108
- interned_metadata** elems;
183
+ InternedMetadata::BucketLink* elems;
109
184
  size_t count;
110
185
  size_t capacity;
111
186
  /** Estimate of the number of unreferenced mdelems in the hash table.
@@ -126,7 +201,7 @@ void grpc_mdctx_global_init(void) {
126
201
  shard->count = 0;
127
202
  gpr_atm_no_barrier_store(&shard->free_estimate, 0);
128
203
  shard->capacity = INITIAL_SHARD_CAPACITY;
129
- shard->elems = static_cast<interned_metadata**>(
204
+ shard->elems = static_cast<InternedMetadata::BucketLink*>(
130
205
  gpr_zalloc(sizeof(*shard->elems) * shard->capacity));
131
206
  }
132
207
  }
@@ -136,7 +211,6 @@ void grpc_mdctx_global_shutdown() {
136
211
  mdtab_shard* shard = &g_shards[i];
137
212
  gpr_mu_destroy(&shard->mu);
138
213
  gc_mdtab(shard);
139
- /* TODO(ctiller): GPR_ASSERT(shard->count == 0); */
140
214
  if (shard->count != 0) {
141
215
  gpr_log(GPR_DEBUG, "WARNING: %" PRIuPTR " metadata elements were leaked",
142
216
  shard->count);
@@ -144,6 +218,7 @@ void grpc_mdctx_global_shutdown() {
144
218
  abort();
145
219
  }
146
220
  }
221
+ GPR_DEBUG_ASSERT(shard->count == 0);
147
222
  gpr_free(shard->elems);
148
223
  }
149
224
  }
@@ -154,57 +229,34 @@ static int is_mdelem_static(grpc_mdelem e) {
154
229
  &grpc_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT];
155
230
  }
156
231
 
157
- static void ref_md_locked(mdtab_shard* shard,
158
- interned_metadata* md DEBUG_ARGS) {
232
+ void InternedMetadata::RefWithShardLocked(mdtab_shard* shard) {
159
233
  #ifndef NDEBUG
160
234
  if (grpc_trace_metadata.enabled()) {
161
- char* key_str = grpc_slice_to_c_string(md->key);
162
- char* value_str = grpc_slice_to_c_string(md->value);
163
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
164
- "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", (void*)md,
165
- gpr_atm_no_barrier_load(&md->refcnt),
166
- gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
235
+ char* key_str = grpc_slice_to_c_string(key_);
236
+ char* value_str = grpc_slice_to_c_string(value_);
237
+ intptr_t value = RefValue();
238
+ gpr_log(__FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG,
239
+ "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", this, value,
240
+ value + 1, key_str, value_str);
167
241
  gpr_free(key_str);
168
242
  gpr_free(value_str);
169
243
  }
170
244
  #endif
171
- if (0 == gpr_atm_no_barrier_fetch_add(&md->refcnt, 1)) {
245
+ if (FirstRef()) {
172
246
  gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1);
173
247
  }
174
248
  }
175
249
 
176
250
  static void gc_mdtab(mdtab_shard* shard) {
177
251
  GPR_TIMER_SCOPE("gc_mdtab", 0);
178
-
179
- size_t i;
180
- interned_metadata** prev_next;
181
- interned_metadata *md, *next;
182
- gpr_atm num_freed = 0;
183
-
184
- for (i = 0; i < shard->capacity; i++) {
185
- prev_next = &shard->elems[i];
186
- for (md = shard->elems[i]; md; md = next) {
187
- void* user_data =
188
- (void*)gpr_atm_no_barrier_load(&md->user_data.user_data);
189
- next = md->bucket_next;
190
- if (gpr_atm_acq_load(&md->refcnt) == 0) {
191
- grpc_slice_unref_internal(md->key);
192
- grpc_slice_unref_internal(md->value);
193
- if (md->user_data.user_data) {
194
- ((destroy_user_data_func)gpr_atm_no_barrier_load(
195
- &md->user_data.destroy_user_data))(user_data);
196
- }
197
- gpr_mu_destroy(&md->user_data.mu_user_data);
198
- gpr_free(md);
199
- *prev_next = next;
200
- num_freed++;
201
- shard->count--;
202
- } else {
203
- prev_next = &md->bucket_next;
204
- }
205
- }
252
+ size_t num_freed = 0;
253
+ for (size_t i = 0; i < shard->capacity; ++i) {
254
+ intptr_t freed = InternedMetadata::CleanupLinkedMetadata(&shard->elems[i]);
255
+ num_freed += freed;
256
+ shard->count -= freed;
206
257
  }
207
- gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -num_freed);
258
+ gpr_atm_no_barrier_fetch_add(&shard->free_estimate,
259
+ -static_cast<intptr_t>(num_freed));
208
260
  }
209
261
 
210
262
  static void grow_mdtab(mdtab_shard* shard) {
@@ -212,22 +264,21 @@ static void grow_mdtab(mdtab_shard* shard) {
212
264
 
213
265
  size_t capacity = shard->capacity * 2;
214
266
  size_t i;
215
- interned_metadata** mdtab;
216
- interned_metadata *md, *next;
267
+ InternedMetadata::BucketLink* mdtab;
268
+ InternedMetadata *md, *next;
217
269
  uint32_t hash;
218
270
 
219
- mdtab = static_cast<interned_metadata**>(
220
- gpr_zalloc(sizeof(interned_metadata*) * capacity));
271
+ mdtab = static_cast<InternedMetadata::BucketLink*>(
272
+ gpr_zalloc(sizeof(InternedMetadata::BucketLink) * capacity));
221
273
 
222
274
  for (i = 0; i < shard->capacity; i++) {
223
- for (md = shard->elems[i]; md; md = next) {
275
+ for (md = shard->elems[i].next; md; md = next) {
224
276
  size_t idx;
225
- hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
226
- grpc_slice_hash(md->value));
227
- next = md->bucket_next;
277
+ hash = md->hash();
278
+ next = md->bucket_next();
228
279
  idx = TABLE_IDX(hash, capacity);
229
- md->bucket_next = mdtab[idx];
230
- mdtab[idx] = md;
280
+ md->set_bucket_next(mdtab[idx].next);
281
+ mdtab[idx].next = md;
231
282
  }
232
283
  }
233
284
  gpr_free(shard->elems);
@@ -247,34 +298,22 @@ static void rehash_mdtab(mdtab_shard* shard) {
247
298
  grpc_mdelem grpc_mdelem_create(
248
299
  const grpc_slice& key, const grpc_slice& value,
249
300
  grpc_mdelem_data* compatible_external_backing_store) {
301
+ // External storage if either slice is not interned and the caller already
302
+ // created a backing store. If no backing store, we allocate one.
250
303
  if (!grpc_slice_is_interned(key) || !grpc_slice_is_interned(value)) {
251
304
  if (compatible_external_backing_store != nullptr) {
305
+ // Caller provided backing store.
252
306
  return GRPC_MAKE_MDELEM(compatible_external_backing_store,
253
307
  GRPC_MDELEM_STORAGE_EXTERNAL);
308
+ } else {
309
+ // We allocate backing store.
310
+ return GRPC_MAKE_MDELEM(grpc_core::New<AllocatedMetadata>(key, value),
311
+ GRPC_MDELEM_STORAGE_ALLOCATED);
254
312
  }
255
-
256
- allocated_metadata* allocated =
257
- static_cast<allocated_metadata*>(gpr_malloc(sizeof(*allocated)));
258
- allocated->key = grpc_slice_ref_internal(key);
259
- allocated->value = grpc_slice_ref_internal(value);
260
- gpr_atm_rel_store(&allocated->refcnt, 1);
261
- allocated->user_data.user_data = 0;
262
- allocated->user_data.destroy_user_data = 0;
263
- gpr_mu_init(&allocated->user_data.mu_user_data);
264
- #ifndef NDEBUG
265
- if (grpc_trace_metadata.enabled()) {
266
- char* key_str = grpc_slice_to_c_string(allocated->key);
267
- char* value_str = grpc_slice_to_c_string(allocated->value);
268
- gpr_log(GPR_DEBUG, "ELM ALLOC:%p:%" PRIdPTR ": '%s' = '%s'",
269
- (void*)allocated, gpr_atm_no_barrier_load(&allocated->refcnt),
270
- key_str, value_str);
271
- gpr_free(key_str);
272
- gpr_free(value_str);
273
- }
274
- #endif
275
- return GRPC_MAKE_MDELEM(allocated, GRPC_MDELEM_STORAGE_ALLOCATED);
276
313
  }
277
314
 
315
+ // Not all static slice input yields a statically stored metadata element.
316
+ // It may be worth documenting why.
278
317
  if (GRPC_IS_STATIC_METADATA_STRING(key) &&
279
318
  GRPC_IS_STATIC_METADATA_STRING(value)) {
280
319
  grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings(
@@ -286,7 +325,7 @@ grpc_mdelem grpc_mdelem_create(
286
325
 
287
326
  uint32_t hash =
288
327
  GRPC_MDSTR_KV_HASH(grpc_slice_hash(key), grpc_slice_hash(value));
289
- interned_metadata* md;
328
+ InternedMetadata* md;
290
329
  mdtab_shard* shard = &g_shards[SHARD_IDX(hash)];
291
330
  size_t idx;
292
331
 
@@ -296,34 +335,18 @@ grpc_mdelem grpc_mdelem_create(
296
335
 
297
336
  idx = TABLE_IDX(hash, shard->capacity);
298
337
  /* search for an existing pair */
299
- for (md = shard->elems[idx]; md; md = md->bucket_next) {
300
- if (grpc_slice_eq(key, md->key) && grpc_slice_eq(value, md->value)) {
301
- REF_MD_LOCKED(shard, md);
338
+ for (md = shard->elems[idx].next; md; md = md->bucket_next()) {
339
+ if (grpc_slice_eq(key, md->key()) && grpc_slice_eq(value, md->value())) {
340
+ md->RefWithShardLocked(shard);
302
341
  gpr_mu_unlock(&shard->mu);
303
342
  return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED);
304
343
  }
305
344
  }
306
345
 
307
346
  /* not found: create a new pair */
308
- md = static_cast<interned_metadata*>(gpr_malloc(sizeof(interned_metadata)));
309
- gpr_atm_rel_store(&md->refcnt, 1);
310
- md->key = grpc_slice_ref_internal(key);
311
- md->value = grpc_slice_ref_internal(value);
312
- md->user_data.user_data = 0;
313
- md->user_data.destroy_user_data = 0;
314
- md->bucket_next = shard->elems[idx];
315
- shard->elems[idx] = md;
316
- gpr_mu_init(&md->user_data.mu_user_data);
317
- #ifndef NDEBUG
318
- if (grpc_trace_metadata.enabled()) {
319
- char* key_str = grpc_slice_to_c_string(md->key);
320
- char* value_str = grpc_slice_to_c_string(md->value);
321
- gpr_log(GPR_DEBUG, "ELM NEW:%p:%" PRIdPTR ": '%s' = '%s'", (void*)md,
322
- gpr_atm_no_barrier_load(&md->refcnt), key_str, value_str);
323
- gpr_free(key_str);
324
- gpr_free(value_str);
325
- }
326
- #endif
347
+ md = grpc_core::New<InternedMetadata>(key, value, hash,
348
+ shard->elems[idx].next);
349
+ shard->elems[idx].next = md;
327
350
  shard->count++;
328
351
 
329
352
  if (shard->count > shard->capacity * 2) {
@@ -354,130 +377,10 @@ grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata) {
354
377
  changed ? nullptr : reinterpret_cast<grpc_mdelem_data*>(metadata));
355
378
  }
356
379
 
357
- grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd DEBUG_ARGS) {
358
- switch (GRPC_MDELEM_STORAGE(gmd)) {
359
- case GRPC_MDELEM_STORAGE_EXTERNAL:
360
- case GRPC_MDELEM_STORAGE_STATIC:
361
- break;
362
- case GRPC_MDELEM_STORAGE_INTERNED: {
363
- interned_metadata* md =
364
- reinterpret_cast<interned_metadata*> GRPC_MDELEM_DATA(gmd);
365
- #ifndef NDEBUG
366
- if (grpc_trace_metadata.enabled()) {
367
- char* key_str = grpc_slice_to_c_string(md->key);
368
- char* value_str = grpc_slice_to_c_string(md->value);
369
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
370
- "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
371
- (void*)md, gpr_atm_no_barrier_load(&md->refcnt),
372
- gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
373
- gpr_free(key_str);
374
- gpr_free(value_str);
375
- }
376
- #endif
377
- /* we can assume the ref count is >= 1 as the application is calling
378
- this function - meaning that no adjustment to mdtab_free is necessary,
379
- simplifying the logic here to be just an atomic increment */
380
- /* use C assert to have this removed in opt builds */
381
- GPR_ASSERT(gpr_atm_no_barrier_load(&md->refcnt) >= 1);
382
- gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
383
- break;
384
- }
385
- case GRPC_MDELEM_STORAGE_ALLOCATED: {
386
- allocated_metadata* md =
387
- reinterpret_cast<allocated_metadata*> GRPC_MDELEM_DATA(gmd);
388
- #ifndef NDEBUG
389
- if (grpc_trace_metadata.enabled()) {
390
- char* key_str = grpc_slice_to_c_string(md->key);
391
- char* value_str = grpc_slice_to_c_string(md->value);
392
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
393
- "ELM REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
394
- (void*)md, gpr_atm_no_barrier_load(&md->refcnt),
395
- gpr_atm_no_barrier_load(&md->refcnt) + 1, key_str, value_str);
396
- gpr_free(key_str);
397
- gpr_free(value_str);
398
- }
399
- #endif
400
- /* we can assume the ref count is >= 1 as the application is calling
401
- this function - meaning that no adjustment to mdtab_free is necessary,
402
- simplifying the logic here to be just an atomic increment */
403
- /* use C assert to have this removed in opt builds */
404
- gpr_atm_no_barrier_fetch_add(&md->refcnt, 1);
405
- break;
406
- }
407
- }
408
- return gmd;
409
- }
410
-
411
- void grpc_mdelem_unref(grpc_mdelem gmd DEBUG_ARGS) {
412
- switch (GRPC_MDELEM_STORAGE(gmd)) {
413
- case GRPC_MDELEM_STORAGE_EXTERNAL:
414
- case GRPC_MDELEM_STORAGE_STATIC:
415
- break;
416
- case GRPC_MDELEM_STORAGE_INTERNED: {
417
- interned_metadata* md =
418
- reinterpret_cast<interned_metadata*> GRPC_MDELEM_DATA(gmd);
419
- #ifndef NDEBUG
420
- if (grpc_trace_metadata.enabled()) {
421
- char* key_str = grpc_slice_to_c_string(md->key);
422
- char* value_str = grpc_slice_to_c_string(md->value);
423
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
424
- "ELM UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
425
- (void*)md, gpr_atm_no_barrier_load(&md->refcnt),
426
- gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str);
427
- gpr_free(key_str);
428
- gpr_free(value_str);
429
- }
430
- #endif
431
- uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash(md->key),
432
- grpc_slice_hash(md->value));
433
- const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
434
- GPR_ASSERT(prev_refcount >= 1);
435
- if (1 == prev_refcount) {
436
- /* once the refcount hits zero, some other thread can come along and
437
- free md at any time: it's unsafe from this point on to access it */
438
- mdtab_shard* shard = &g_shards[SHARD_IDX(hash)];
439
- gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
440
- }
441
- break;
442
- }
443
- case GRPC_MDELEM_STORAGE_ALLOCATED: {
444
- allocated_metadata* md =
445
- reinterpret_cast<allocated_metadata*> GRPC_MDELEM_DATA(gmd);
446
- #ifndef NDEBUG
447
- if (grpc_trace_metadata.enabled()) {
448
- char* key_str = grpc_slice_to_c_string(md->key);
449
- char* value_str = grpc_slice_to_c_string(md->value);
450
- gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG,
451
- "ELM UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'",
452
- (void*)md, gpr_atm_no_barrier_load(&md->refcnt),
453
- gpr_atm_no_barrier_load(&md->refcnt) - 1, key_str, value_str);
454
- gpr_free(key_str);
455
- gpr_free(value_str);
456
- }
457
- #endif
458
- const gpr_atm prev_refcount = gpr_atm_full_fetch_add(&md->refcnt, -1);
459
- GPR_ASSERT(prev_refcount >= 1);
460
- if (1 == prev_refcount) {
461
- grpc_slice_unref_internal(md->key);
462
- grpc_slice_unref_internal(md->value);
463
- if (md->user_data.user_data) {
464
- destroy_user_data_func destroy_user_data =
465
- (destroy_user_data_func)gpr_atm_no_barrier_load(
466
- &md->user_data.destroy_user_data);
467
- destroy_user_data((void*)md->user_data.user_data);
468
- }
469
- gpr_mu_destroy(&md->user_data.mu_user_data);
470
- gpr_free(md);
471
- }
472
- break;
473
- }
474
- }
475
- }
476
-
477
380
  static void* get_user_data(UserData* user_data, void (*destroy_func)(void*)) {
478
- if (gpr_atm_acq_load(&user_data->destroy_user_data) ==
479
- (gpr_atm)destroy_func) {
480
- return (void*)gpr_atm_no_barrier_load(&user_data->user_data);
381
+ if (user_data->destroy_user_data.Load(grpc_core::MemoryOrder::ACQUIRE) ==
382
+ destroy_func) {
383
+ return user_data->data.Load(grpc_core::MemoryOrder::RELAXED);
481
384
  } else {
482
385
  return nullptr;
483
386
  }
@@ -491,57 +394,52 @@ void* grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void*)) {
491
394
  return (void*)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
492
395
  grpc_static_mdelem_table];
493
396
  case GRPC_MDELEM_STORAGE_ALLOCATED: {
494
- allocated_metadata* am =
495
- reinterpret_cast<allocated_metadata*>(GRPC_MDELEM_DATA(md));
496
- return get_user_data(&am->user_data, destroy_func);
397
+ auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md));
398
+ return get_user_data(am->user_data(), destroy_func);
497
399
  }
498
400
  case GRPC_MDELEM_STORAGE_INTERNED: {
499
- interned_metadata* im =
500
- reinterpret_cast<interned_metadata*> GRPC_MDELEM_DATA(md);
501
- return get_user_data(&im->user_data, destroy_func);
401
+ auto* im = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(md);
402
+ return get_user_data(im->user_data(), destroy_func);
502
403
  }
503
404
  }
504
405
  GPR_UNREACHABLE_CODE(return nullptr);
505
406
  }
506
407
 
507
408
  static void* set_user_data(UserData* ud, void (*destroy_func)(void*),
508
- void* user_data) {
509
- GPR_ASSERT((user_data == nullptr) == (destroy_func == nullptr));
510
- gpr_mu_lock(&ud->mu_user_data);
511
- if (gpr_atm_no_barrier_load(&ud->destroy_user_data)) {
409
+ void* data) {
410
+ GPR_ASSERT((data == nullptr) == (destroy_func == nullptr));
411
+ grpc_core::ReleasableMutexLock lock(&ud->mu_user_data);
412
+ if (ud->destroy_user_data.Load(grpc_core::MemoryOrder::RELAXED)) {
512
413
  /* user data can only be set once */
513
- gpr_mu_unlock(&ud->mu_user_data);
414
+ lock.Unlock();
514
415
  if (destroy_func != nullptr) {
515
- destroy_func(user_data);
416
+ destroy_func(data);
516
417
  }
517
- return (void*)gpr_atm_no_barrier_load(&ud->user_data);
418
+ return ud->data.Load(grpc_core::MemoryOrder::RELAXED);
518
419
  }
519
- gpr_atm_no_barrier_store(&ud->user_data, (gpr_atm)user_data);
520
- gpr_atm_rel_store(&ud->destroy_user_data, (gpr_atm)destroy_func);
521
- gpr_mu_unlock(&ud->mu_user_data);
522
- return user_data;
420
+ ud->data.Store(data, grpc_core::MemoryOrder::RELAXED);
421
+ ud->destroy_user_data.Store(destroy_func, grpc_core::MemoryOrder::RELEASE);
422
+ return data;
523
423
  }
524
424
 
525
425
  void* grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void*),
526
- void* user_data) {
426
+ void* data) {
527
427
  switch (GRPC_MDELEM_STORAGE(md)) {
528
428
  case GRPC_MDELEM_STORAGE_EXTERNAL:
529
- destroy_func(user_data);
429
+ destroy_func(data);
530
430
  return nullptr;
531
431
  case GRPC_MDELEM_STORAGE_STATIC:
532
- destroy_func(user_data);
432
+ destroy_func(data);
533
433
  return (void*)grpc_static_mdelem_user_data[GRPC_MDELEM_DATA(md) -
534
434
  grpc_static_mdelem_table];
535
435
  case GRPC_MDELEM_STORAGE_ALLOCATED: {
536
- allocated_metadata* am =
537
- reinterpret_cast<allocated_metadata*>(GRPC_MDELEM_DATA(md));
538
- return set_user_data(&am->user_data, destroy_func, user_data);
436
+ auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md));
437
+ return set_user_data(am->user_data(), destroy_func, data);
539
438
  }
540
439
  case GRPC_MDELEM_STORAGE_INTERNED: {
541
- interned_metadata* im =
542
- reinterpret_cast<interned_metadata*> GRPC_MDELEM_DATA(md);
440
+ auto* im = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(md);
543
441
  GPR_ASSERT(!is_mdelem_static(md));
544
- return set_user_data(&im->user_data, destroy_func, user_data);
442
+ return set_user_data(im->user_data(), destroy_func, data);
545
443
  }
546
444
  }
547
445
  GPR_UNREACHABLE_CODE(return nullptr);
@@ -554,3 +452,33 @@ bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b) {
554
452
  return grpc_slice_eq(GRPC_MDKEY(a), GRPC_MDKEY(b)) &&
555
453
  grpc_slice_eq(GRPC_MDVALUE(a), GRPC_MDVALUE(b));
556
454
  }
455
+
456
+ static void note_disposed_interned_metadata(uint32_t hash) {
457
+ mdtab_shard* shard = &g_shards[SHARD_IDX(hash)];
458
+ gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1);
459
+ }
460
+
461
+ void grpc_mdelem_do_unref(grpc_mdelem gmd DEBUG_ARGS) {
462
+ switch (GRPC_MDELEM_STORAGE(gmd)) {
463
+ case GRPC_MDELEM_STORAGE_EXTERNAL:
464
+ case GRPC_MDELEM_STORAGE_STATIC:
465
+ return;
466
+ case GRPC_MDELEM_STORAGE_INTERNED: {
467
+ auto* md = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(gmd);
468
+ uint32_t hash = md->hash();
469
+ if (GPR_UNLIKELY(md->Unref(FWD_DEBUG_ARGS))) {
470
+ /* once the refcount hits zero, some other thread can come along and
471
+ free md at any time: it's unsafe from this point on to access it */
472
+ note_disposed_interned_metadata(hash);
473
+ }
474
+ break;
475
+ }
476
+ case GRPC_MDELEM_STORAGE_ALLOCATED: {
477
+ auto* md = reinterpret_cast<AllocatedMetadata*> GRPC_MDELEM_DATA(gmd);
478
+ if (GPR_UNLIKELY(md->Unref(FWD_DEBUG_ARGS))) {
479
+ grpc_core::Delete(md);
480
+ }
481
+ break;
482
+ }
483
+ }
484
+ }