Merge pull request #3423 from ctiller/shindig

Rearchitect background work: phase 1
pull/3474/head^2
Nicolas Noble 10 years ago
commit ff60024eaf
  1. 27
      BUILD
  2. 74
      Makefile
  3. 67
      build.yaml
  4. 14
      gRPC.podspec
  5. 34
      grpc.gyp
  6. 6
      include/grpc++/impl/call.h
  7. 6
      src/core/census/context.h
  8. 103
      src/core/census/grpc_filter.c
  9. 8
      src/core/channel/channel_args.c
  10. 4
      src/core/channel/channel_args.h
  11. 41
      src/core/channel/channel_stack.c
  12. 43
      src/core/channel/channel_stack.h
  13. 278
      src/core/channel/client_channel.c
  14. 15
      src/core/channel/client_channel.h
  15. 20
      src/core/channel/compress_filter.c
  16. 31
      src/core/channel/connected_channel.c
  17. 4
      src/core/channel/connected_channel.h
  18. 63
      src/core/channel/http_client_filter.c
  19. 46
      src/core/channel/http_server_filter.c
  20. 23
      src/core/channel/noop_filter.c
  21. 8
      src/core/client_config/client_config.c
  22. 3
      src/core/client_config/client_config.h
  23. 21
      src/core/client_config/connector.c
  24. 19
      src/core/client_config/connector.h
  25. 165
      src/core/client_config/lb_policies/pick_first.c
  26. 137
      src/core/client_config/lb_policies/round_robin.c
  27. 1
      src/core/client_config/lb_policies/round_robin.h
  28. 42
      src/core/client_config/lb_policy.c
  29. 56
      src/core/client_config/lb_policy.h
  30. 9
      src/core/client_config/lb_policy_factory.c
  31. 6
      src/core/client_config/lb_policy_registry.c
  32. 28
      src/core/client_config/resolver.c
  33. 31
      src/core/client_config/resolver.h
  34. 15
      src/core/client_config/resolver_factory.c
  35. 13
      src/core/client_config/resolver_factory.h
  36. 8
      src/core/client_config/resolver_registry.c
  37. 76
      src/core/client_config/resolvers/dns_resolver.c
  38. 85
      src/core/client_config/resolvers/sockaddr_resolver.c
  39. 96
      src/core/client_config/resolvers/zookeeper_resolver.c
  40. 251
      src/core/client_config/subchannel.c
  41. 49
      src/core/client_config/subchannel.h
  42. 15
      src/core/client_config/subchannel_factory.c
  43. 11
      src/core/client_config/subchannel_factory.h
  44. 2
      src/core/client_config/subchannel_factory_decorators/add_channel_arg.h
  45. 10
      src/core/client_config/subchannel_factory_decorators/merge_channel_args.c
  46. 2
      src/core/client_config/subchannel_factory_decorators/merge_channel_args.h
  47. 3
      src/core/client_config/uri_parser.c
  48. 2
      src/core/compression/algorithm.c
  49. 18
      src/core/compression/message_compress.c
  50. 4
      src/core/compression/message_compress.h
  51. 187
      src/core/httpcli/httpcli.c
  52. 30
      src/core/httpcli/httpcli.h
  53. 32
      src/core/httpcli/httpcli_security_connector.c
  54. 8
      src/core/httpcli/parser.h
  55. 65
      src/core/iomgr/alarm.c
  56. 12
      src/core/iomgr/alarm.h
  57. 7
      src/core/iomgr/alarm_internal.h
  58. 71
      src/core/iomgr/closure.c
  59. 88
      src/core/iomgr/closure.h
  60. 36
      src/core/iomgr/endpoint.c
  61. 44
      src/core/iomgr/endpoint.h
  62. 62
      src/core/iomgr/exec_ctx.c
  63. 77
      src/core/iomgr/exec_ctx.h
  64. 92
      src/core/iomgr/fd_posix.c
  65. 25
      src/core/iomgr/fd_posix.h
  66. 48
      src/core/iomgr/iocp_windows.c
  67. 10
      src/core/iomgr/iocp_windows.h
  68. 171
      src/core/iomgr/iomgr.c
  69. 37
      src/core/iomgr/iomgr.h
  70. 3
      src/core/iomgr/iomgr_internal.h
  71. 15
      src/core/iomgr/pollset.h
  72. 50
      src/core/iomgr/pollset_multipoller_with_epoll.c
  73. 25
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  74. 124
      src/core/iomgr/pollset_posix.c
  75. 32
      src/core/iomgr/pollset_posix.h
  76. 14
      src/core/iomgr/pollset_set.h
  77. 16
      src/core/iomgr/pollset_set_posix.c
  78. 6
      src/core/iomgr/pollset_set_posix.h
  79. 14
      src/core/iomgr/pollset_set_windows.c
  80. 22
      src/core/iomgr/pollset_windows.c
  81. 5
      src/core/iomgr/resolve_address.h
  82. 8
      src/core/iomgr/resolve_address_posix.c
  83. 6
      src/core/iomgr/resolve_address_windows.c
  84. 4
      src/core/iomgr/sockaddr_utils.c
  85. 3
      src/core/iomgr/socket_windows.c
  86. 6
      src/core/iomgr/socket_windows.h
  87. 5
      src/core/iomgr/tcp_client.h
  88. 57
      src/core/iomgr/tcp_client_posix.c
  89. 43
      src/core/iomgr/tcp_client_windows.c
  90. 138
      src/core/iomgr/tcp_posix.c
  91. 12
      src/core/iomgr/tcp_server.h
  92. 63
      src/core/iomgr/tcp_server_posix.c
  93. 67
      src/core/iomgr/tcp_server_windows.c
  94. 92
      src/core/iomgr/tcp_windows.c
  95. 6
      src/core/iomgr/time_averaged_stats.c
  96. 6
      src/core/iomgr/time_averaged_stats.h
  97. 55
      src/core/iomgr/udp_server.c
  98. 9
      src/core/iomgr/udp_server.h
  99. 10
      src/core/iomgr/wakeup_fd_eventfd.c
  100. 12
      src/core/iomgr/wakeup_fd_pipe.c
  101. Some files were not shown because too many files have changed in this diff Show More

27
BUILD

@ -179,8 +179,10 @@ cc_library(
"src/core/iomgr/alarm.h",
"src/core/iomgr/alarm_heap.h",
"src/core/iomgr/alarm_internal.h",
"src/core/iomgr/closure.h",
"src/core/iomgr/endpoint.h",
"src/core/iomgr/endpoint_pair.h",
"src/core/iomgr/exec_ctx.h",
"src/core/iomgr/fd_posix.h",
"src/core/iomgr/iocp_windows.h",
"src/core/iomgr/iomgr.h",
@ -207,6 +209,9 @@ cc_library(
"src/core/iomgr/udp_server.h",
"src/core/iomgr/wakeup_fd_pipe.h",
"src/core/iomgr/wakeup_fd_posix.h",
"src/core/iomgr/workqueue.h",
"src/core/iomgr/workqueue_posix.h",
"src/core/iomgr/workqueue_windows.h",
"src/core/json/json.h",
"src/core/json/json_common.h",
"src/core/json/json_reader.h",
@ -307,9 +312,11 @@ cc_library(
"src/core/httpcli/parser.c",
"src/core/iomgr/alarm.c",
"src/core/iomgr/alarm_heap.c",
"src/core/iomgr/closure.c",
"src/core/iomgr/endpoint.c",
"src/core/iomgr/endpoint_pair_posix.c",
"src/core/iomgr/endpoint_pair_windows.c",
"src/core/iomgr/exec_ctx.c",
"src/core/iomgr/fd_posix.c",
"src/core/iomgr/iocp_windows.c",
"src/core/iomgr/iomgr.c",
@ -340,6 +347,8 @@ cc_library(
"src/core/iomgr/wakeup_fd_nospecial.c",
"src/core/iomgr/wakeup_fd_pipe.c",
"src/core/iomgr/wakeup_fd_posix.c",
"src/core/iomgr/workqueue_posix.c",
"src/core/iomgr/workqueue_windows.c",
"src/core/json/json.c",
"src/core/json/json_reader.c",
"src/core/json/json_string.c",
@ -455,8 +464,10 @@ cc_library(
"src/core/iomgr/alarm.h",
"src/core/iomgr/alarm_heap.h",
"src/core/iomgr/alarm_internal.h",
"src/core/iomgr/closure.h",
"src/core/iomgr/endpoint.h",
"src/core/iomgr/endpoint_pair.h",
"src/core/iomgr/exec_ctx.h",
"src/core/iomgr/fd_posix.h",
"src/core/iomgr/iocp_windows.h",
"src/core/iomgr/iomgr.h",
@ -483,6 +494,9 @@ cc_library(
"src/core/iomgr/udp_server.h",
"src/core/iomgr/wakeup_fd_pipe.h",
"src/core/iomgr/wakeup_fd_posix.h",
"src/core/iomgr/workqueue.h",
"src/core/iomgr/workqueue_posix.h",
"src/core/iomgr/workqueue_windows.h",
"src/core/json/json.h",
"src/core/json/json_common.h",
"src/core/json/json_reader.h",
@ -563,9 +577,11 @@ cc_library(
"src/core/httpcli/parser.c",
"src/core/iomgr/alarm.c",
"src/core/iomgr/alarm_heap.c",
"src/core/iomgr/closure.c",
"src/core/iomgr/endpoint.c",
"src/core/iomgr/endpoint_pair_posix.c",
"src/core/iomgr/endpoint_pair_windows.c",
"src/core/iomgr/exec_ctx.c",
"src/core/iomgr/fd_posix.c",
"src/core/iomgr/iocp_windows.c",
"src/core/iomgr/iomgr.c",
@ -596,6 +612,8 @@ cc_library(
"src/core/iomgr/wakeup_fd_nospecial.c",
"src/core/iomgr/wakeup_fd_pipe.c",
"src/core/iomgr/wakeup_fd_posix.c",
"src/core/iomgr/workqueue_posix.c",
"src/core/iomgr/workqueue_windows.c",
"src/core/json/json.c",
"src/core/json/json_reader.c",
"src/core/json/json_string.c",
@ -1082,9 +1100,11 @@ objc_library(
"src/core/httpcli/parser.c",
"src/core/iomgr/alarm.c",
"src/core/iomgr/alarm_heap.c",
"src/core/iomgr/closure.c",
"src/core/iomgr/endpoint.c",
"src/core/iomgr/endpoint_pair_posix.c",
"src/core/iomgr/endpoint_pair_windows.c",
"src/core/iomgr/exec_ctx.c",
"src/core/iomgr/fd_posix.c",
"src/core/iomgr/iocp_windows.c",
"src/core/iomgr/iomgr.c",
@ -1115,6 +1135,8 @@ objc_library(
"src/core/iomgr/wakeup_fd_nospecial.c",
"src/core/iomgr/wakeup_fd_pipe.c",
"src/core/iomgr/wakeup_fd_posix.c",
"src/core/iomgr/workqueue_posix.c",
"src/core/iomgr/workqueue_windows.c",
"src/core/json/json.c",
"src/core/json/json_reader.c",
"src/core/json/json_string.c",
@ -1227,8 +1249,10 @@ objc_library(
"src/core/iomgr/alarm.h",
"src/core/iomgr/alarm_heap.h",
"src/core/iomgr/alarm_internal.h",
"src/core/iomgr/closure.h",
"src/core/iomgr/endpoint.h",
"src/core/iomgr/endpoint_pair.h",
"src/core/iomgr/exec_ctx.h",
"src/core/iomgr/fd_posix.h",
"src/core/iomgr/iocp_windows.h",
"src/core/iomgr/iomgr.h",
@ -1255,6 +1279,9 @@ objc_library(
"src/core/iomgr/udp_server.h",
"src/core/iomgr/wakeup_fd_pipe.h",
"src/core/iomgr/wakeup_fd_posix.h",
"src/core/iomgr/workqueue.h",
"src/core/iomgr/workqueue_posix.h",
"src/core/iomgr/workqueue_windows.h",
"src/core/json/json.h",
"src/core/json/json_common.h",
"src/core/json/json_reader.h",

File diff suppressed because one or more lines are too long

@ -55,18 +55,20 @@ filegroups:
src/core/client_config/uri_parser.h, src/core/compression/message_compress.h,
src/core/debug/trace.h, src/core/httpcli/format_request.h, src/core/httpcli/httpcli.h,
src/core/httpcli/parser.h, src/core/iomgr/alarm.h, src/core/iomgr/alarm_heap.h,
src/core/iomgr/alarm_internal.h, src/core/iomgr/endpoint.h, src/core/iomgr/endpoint_pair.h,
src/core/iomgr/fd_posix.h, src/core/iomgr/iocp_windows.h, src/core/iomgr/iomgr.h,
src/core/iomgr/iomgr_internal.h, src/core/iomgr/iomgr_posix.h, src/core/iomgr/pollset.h,
src/core/iomgr/pollset_posix.h, src/core/iomgr/pollset_set.h, src/core/iomgr/pollset_set_posix.h,
src/core/iomgr/pollset_set_windows.h, src/core/iomgr/pollset_windows.h, src/core/iomgr/resolve_address.h,
src/core/iomgr/sockaddr.h, src/core/iomgr/sockaddr_posix.h, src/core/iomgr/sockaddr_utils.h,
src/core/iomgr/sockaddr_win32.h, src/core/iomgr/socket_utils_posix.h, src/core/iomgr/socket_windows.h,
src/core/iomgr/tcp_client.h, src/core/iomgr/tcp_posix.h, src/core/iomgr/tcp_server.h,
src/core/iomgr/tcp_windows.h, src/core/iomgr/time_averaged_stats.h, src/core/iomgr/udp_server.h,
src/core/iomgr/wakeup_fd_pipe.h, src/core/iomgr/wakeup_fd_posix.h, src/core/json/json.h,
src/core/json/json_common.h, src/core/json/json_reader.h, src/core/json/json_writer.h,
src/core/profiling/timers.h, src/core/statistics/census_interface.h, src/core/statistics/census_rpc_stats.h,
src/core/iomgr/alarm_internal.h, src/core/iomgr/closure.h, src/core/iomgr/endpoint.h,
src/core/iomgr/endpoint_pair.h, src/core/iomgr/exec_ctx.h, src/core/iomgr/fd_posix.h,
src/core/iomgr/iocp_windows.h, src/core/iomgr/iomgr.h, src/core/iomgr/iomgr_internal.h,
src/core/iomgr/iomgr_posix.h, src/core/iomgr/pollset.h, src/core/iomgr/pollset_posix.h,
src/core/iomgr/pollset_set.h, src/core/iomgr/pollset_set_posix.h, src/core/iomgr/pollset_set_windows.h,
src/core/iomgr/pollset_windows.h, src/core/iomgr/resolve_address.h, src/core/iomgr/sockaddr.h,
src/core/iomgr/sockaddr_posix.h, src/core/iomgr/sockaddr_utils.h, src/core/iomgr/sockaddr_win32.h,
src/core/iomgr/socket_utils_posix.h, src/core/iomgr/socket_windows.h, src/core/iomgr/tcp_client.h,
src/core/iomgr/tcp_posix.h, src/core/iomgr/tcp_server.h, src/core/iomgr/tcp_windows.h,
src/core/iomgr/time_averaged_stats.h, src/core/iomgr/udp_server.h, src/core/iomgr/wakeup_fd_pipe.h,
src/core/iomgr/wakeup_fd_posix.h, src/core/iomgr/workqueue.h, src/core/iomgr/workqueue_posix.h,
src/core/iomgr/workqueue_windows.h, src/core/json/json.h, src/core/json/json_common.h,
src/core/json/json_reader.h, src/core/json/json_writer.h, src/core/profiling/timers.h,
src/core/statistics/census_interface.h, src/core/statistics/census_rpc_stats.h,
src/core/surface/byte_buffer_queue.h, src/core/surface/call.h, src/core/surface/channel.h,
src/core/surface/completion_queue.h, src/core/surface/event_string.h, src/core/surface/init.h,
src/core/surface/server.h, src/core/surface/surface_trace.h, src/core/transport/chttp2/alpn.h,
@ -96,9 +98,10 @@ filegroups:
src/core/client_config/uri_parser.c, src/core/compression/algorithm.c, src/core/compression/message_compress.c,
src/core/debug/trace.c, src/core/httpcli/format_request.c, src/core/httpcli/httpcli.c,
src/core/httpcli/parser.c, src/core/iomgr/alarm.c, src/core/iomgr/alarm_heap.c,
src/core/iomgr/endpoint.c, src/core/iomgr/endpoint_pair_posix.c, src/core/iomgr/endpoint_pair_windows.c,
src/core/iomgr/fd_posix.c, src/core/iomgr/iocp_windows.c, src/core/iomgr/iomgr.c,
src/core/iomgr/iomgr_posix.c, src/core/iomgr/iomgr_windows.c, src/core/iomgr/pollset_multipoller_with_epoll.c,
src/core/iomgr/closure.c, src/core/iomgr/endpoint.c, src/core/iomgr/endpoint_pair_posix.c,
src/core/iomgr/endpoint_pair_windows.c, src/core/iomgr/exec_ctx.c, src/core/iomgr/fd_posix.c,
src/core/iomgr/iocp_windows.c, src/core/iomgr/iomgr.c, src/core/iomgr/iomgr_posix.c,
src/core/iomgr/iomgr_windows.c, src/core/iomgr/pollset_multipoller_with_epoll.c,
src/core/iomgr/pollset_multipoller_with_poll_posix.c, src/core/iomgr/pollset_posix.c,
src/core/iomgr/pollset_set_posix.c, src/core/iomgr/pollset_set_windows.c, src/core/iomgr/pollset_windows.c,
src/core/iomgr/resolve_address_posix.c, src/core/iomgr/resolve_address_windows.c,
@ -107,16 +110,17 @@ filegroups:
src/core/iomgr/tcp_client_windows.c, src/core/iomgr/tcp_posix.c, src/core/iomgr/tcp_server_posix.c,
src/core/iomgr/tcp_server_windows.c, src/core/iomgr/tcp_windows.c, src/core/iomgr/time_averaged_stats.c,
src/core/iomgr/udp_server.c, src/core/iomgr/wakeup_fd_eventfd.c, src/core/iomgr/wakeup_fd_nospecial.c,
src/core/iomgr/wakeup_fd_pipe.c, src/core/iomgr/wakeup_fd_posix.c, src/core/json/json.c,
src/core/json/json_reader.c, src/core/json/json_string.c, src/core/json/json_writer.c,
src/core/profiling/basic_timers.c, src/core/profiling/stap_timers.c, src/core/surface/byte_buffer.c,
src/core/surface/byte_buffer_queue.c, src/core/surface/byte_buffer_reader.c, src/core/surface/call.c,
src/core/surface/call_details.c, src/core/surface/call_log_batch.c, src/core/surface/channel.c,
src/core/surface/channel_connectivity.c, src/core/surface/channel_create.c, src/core/surface/completion_queue.c,
src/core/surface/event_string.c, src/core/surface/init.c, src/core/surface/lame_client.c,
src/core/surface/metadata_array.c, src/core/surface/server.c, src/core/surface/server_chttp2.c,
src/core/surface/server_create.c, src/core/surface/surface_trace.c, src/core/surface/version.c,
src/core/transport/chttp2/alpn.c, src/core/transport/chttp2/bin_encoder.c, src/core/transport/chttp2/frame_data.c,
src/core/iomgr/wakeup_fd_pipe.c, src/core/iomgr/wakeup_fd_posix.c, src/core/iomgr/workqueue_posix.c,
src/core/iomgr/workqueue_windows.c, src/core/json/json.c, src/core/json/json_reader.c,
src/core/json/json_string.c, src/core/json/json_writer.c, src/core/profiling/basic_timers.c,
src/core/profiling/stap_timers.c, src/core/surface/byte_buffer.c, src/core/surface/byte_buffer_queue.c,
src/core/surface/byte_buffer_reader.c, src/core/surface/call.c, src/core/surface/call_details.c,
src/core/surface/call_log_batch.c, src/core/surface/channel.c, src/core/surface/channel_connectivity.c,
src/core/surface/channel_create.c, src/core/surface/completion_queue.c, src/core/surface/event_string.c,
src/core/surface/init.c, src/core/surface/lame_client.c, src/core/surface/metadata_array.c,
src/core/surface/server.c, src/core/surface/server_chttp2.c, src/core/surface/server_create.c,
src/core/surface/surface_trace.c, src/core/surface/version.c, src/core/transport/chttp2/alpn.c,
src/core/transport/chttp2/bin_encoder.c, src/core/transport/chttp2/frame_data.c,
src/core/transport/chttp2/frame_goaway.c, src/core/transport/chttp2/frame_ping.c,
src/core/transport/chttp2/frame_rst_stream.c, src/core/transport/chttp2/frame_settings.c,
src/core/transport/chttp2/frame_window_update.c, src/core/transport/chttp2/hpack_parser.c,
@ -353,11 +357,6 @@ targets:
language: c
src: [test/core/iomgr/alarm_list_test.c]
deps: [grpc_test_util, grpc, gpr_test_util, gpr]
- name: alarm_test
build: test
language: c
src: [test/core/iomgr/alarm_test.c]
deps: [grpc_test_util, grpc, gpr_test_util, gpr]
- name: alpn_test
build: test
language: c
@ -743,12 +742,18 @@ targets:
language: c
src: [test/core/iomgr/udp_server_test.c]
deps: [grpc_test_util, grpc, gpr_test_util, gpr]
platforms: [posix]
platforms: [mac, linux, posix]
- name: uri_parser_test
build: test
language: c
src: [test/core/client_config/uri_parser_test.c]
deps: [grpc_test_util, grpc, gpr_test_util, gpr]
- name: workqueue_test
build: test
language: c
src: [test/core/iomgr/workqueue_test.c]
deps: [grpc_test_util, grpc, gpr_test_util, gpr]
platforms: [mac, linux, posix]
- name: async_end2end_test
build: test
language: c++

@ -181,8 +181,10 @@ Pod::Spec.new do |s|
'src/core/iomgr/alarm.h',
'src/core/iomgr/alarm_heap.h',
'src/core/iomgr/alarm_internal.h',
'src/core/iomgr/closure.h',
'src/core/iomgr/endpoint.h',
'src/core/iomgr/endpoint_pair.h',
'src/core/iomgr/exec_ctx.h',
'src/core/iomgr/fd_posix.h',
'src/core/iomgr/iocp_windows.h',
'src/core/iomgr/iomgr.h',
@ -209,6 +211,9 @@ Pod::Spec.new do |s|
'src/core/iomgr/udp_server.h',
'src/core/iomgr/wakeup_fd_pipe.h',
'src/core/iomgr/wakeup_fd_posix.h',
'src/core/iomgr/workqueue.h',
'src/core/iomgr/workqueue_posix.h',
'src/core/iomgr/workqueue_windows.h',
'src/core/json/json.h',
'src/core/json/json_common.h',
'src/core/json/json_reader.h',
@ -316,9 +321,11 @@ Pod::Spec.new do |s|
'src/core/httpcli/parser.c',
'src/core/iomgr/alarm.c',
'src/core/iomgr/alarm_heap.c',
'src/core/iomgr/closure.c',
'src/core/iomgr/endpoint.c',
'src/core/iomgr/endpoint_pair_posix.c',
'src/core/iomgr/endpoint_pair_windows.c',
'src/core/iomgr/exec_ctx.c',
'src/core/iomgr/fd_posix.c',
'src/core/iomgr/iocp_windows.c',
'src/core/iomgr/iomgr.c',
@ -349,6 +356,8 @@ Pod::Spec.new do |s|
'src/core/iomgr/wakeup_fd_nospecial.c',
'src/core/iomgr/wakeup_fd_pipe.c',
'src/core/iomgr/wakeup_fd_posix.c',
'src/core/iomgr/workqueue_posix.c',
'src/core/iomgr/workqueue_windows.c',
'src/core/json/json.c',
'src/core/json/json_reader.c',
'src/core/json/json_string.c',
@ -461,8 +470,10 @@ Pod::Spec.new do |s|
'src/core/iomgr/alarm.h',
'src/core/iomgr/alarm_heap.h',
'src/core/iomgr/alarm_internal.h',
'src/core/iomgr/closure.h',
'src/core/iomgr/endpoint.h',
'src/core/iomgr/endpoint_pair.h',
'src/core/iomgr/exec_ctx.h',
'src/core/iomgr/fd_posix.h',
'src/core/iomgr/iocp_windows.h',
'src/core/iomgr/iomgr.h',
@ -489,6 +500,9 @@ Pod::Spec.new do |s|
'src/core/iomgr/udp_server.h',
'src/core/iomgr/wakeup_fd_pipe.h',
'src/core/iomgr/wakeup_fd_posix.h',
'src/core/iomgr/workqueue.h',
'src/core/iomgr/workqueue_posix.h',
'src/core/iomgr/workqueue_windows.h',
'src/core/json/json.h',
'src/core/json/json_common.h',
'src/core/json/json_reader.h',

@ -205,9 +205,11 @@
'src/core/httpcli/parser.c',
'src/core/iomgr/alarm.c',
'src/core/iomgr/alarm_heap.c',
'src/core/iomgr/closure.c',
'src/core/iomgr/endpoint.c',
'src/core/iomgr/endpoint_pair_posix.c',
'src/core/iomgr/endpoint_pair_windows.c',
'src/core/iomgr/exec_ctx.c',
'src/core/iomgr/fd_posix.c',
'src/core/iomgr/iocp_windows.c',
'src/core/iomgr/iomgr.c',
@ -238,6 +240,8 @@
'src/core/iomgr/wakeup_fd_nospecial.c',
'src/core/iomgr/wakeup_fd_pipe.c',
'src/core/iomgr/wakeup_fd_posix.c',
'src/core/iomgr/workqueue_posix.c',
'src/core/iomgr/workqueue_windows.c',
'src/core/json/json.c',
'src/core/json/json_reader.c',
'src/core/json/json_string.c',
@ -387,9 +391,11 @@
'src/core/httpcli/parser.c',
'src/core/iomgr/alarm.c',
'src/core/iomgr/alarm_heap.c',
'src/core/iomgr/closure.c',
'src/core/iomgr/endpoint.c',
'src/core/iomgr/endpoint_pair_posix.c',
'src/core/iomgr/endpoint_pair_windows.c',
'src/core/iomgr/exec_ctx.c',
'src/core/iomgr/fd_posix.c',
'src/core/iomgr/iocp_windows.c',
'src/core/iomgr/iomgr.c',
@ -420,6 +426,8 @@
'src/core/iomgr/wakeup_fd_nospecial.c',
'src/core/iomgr/wakeup_fd_pipe.c',
'src/core/iomgr/wakeup_fd_posix.c',
'src/core/iomgr/workqueue_posix.c',
'src/core/iomgr/workqueue_windows.c',
'src/core/json/json.c',
'src/core/json/json_reader.c',
'src/core/json/json_string.c',
@ -1281,19 +1289,6 @@
'test/core/iomgr/alarm_list_test.c',
]
},
{
'target_name': 'alarm_test',
'type': 'executable',
'dependencies': [
'grpc_test_util',
'grpc',
'gpr_test_util',
'gpr',
],
'sources': [
'test/core/iomgr/alarm_test.c',
]
},
{
'target_name': 'alpn_test',
'type': 'executable',
@ -2229,6 +2224,19 @@
'test/core/client_config/uri_parser_test.c',
]
},
{
'target_name': 'workqueue_test',
'type': 'executable',
'dependencies': [
'grpc_test_util',
'grpc',
'gpr_test_util',
'gpr',
],
'sources': [
'test/core/iomgr/workqueue_test.c',
]
},
{
'target_name': 'h2_compress_bad_hostname_test',
'type': 'executable',

@ -126,11 +126,11 @@ class WriteOptions {
}
private:
void SetBit(const gpr_int32 mask) { flags_ |= mask; }
void SetBit(const gpr_uint32 mask) { flags_ |= mask; }
void ClearBit(const gpr_int32 mask) { flags_ &= ~mask; }
void ClearBit(const gpr_uint32 mask) { flags_ &= ~mask; }
bool GetBit(const gpr_int32 mask) const { return flags_ & mask; }
bool GetBit(const gpr_uint32 mask) const { return (flags_ & mask) != 0; }
gpr_uint32 flags_;
};

@ -41,9 +41,9 @@
struct census_context {
gpr_uint64 op_id; /* Operation identifier - unique per-context */
gpr_uint64 trace_id; /* Globally unique trace identifier */
/* TODO(aveitch) Add census tags:
const census_tag_set *tags;
*/
/* TODO(aveitch) Add census tags:
const census_tag_set *tags;
*/
};
#endif /* GRPC_INTERNAL_CORE_CENSUS_CONTEXT_H */

@ -48,65 +48,67 @@
typedef struct call_data {
census_op_id op_id;
census_context* ctxt;
census_context *ctxt;
gpr_timespec start_ts;
int error;
/* recv callback */
grpc_stream_op_buffer* recv_ops;
grpc_iomgr_closure* on_done_recv;
grpc_stream_op_buffer *recv_ops;
grpc_closure *on_done_recv;
} call_data;
typedef struct channel_data {
grpc_mdstr* path_str; /* pointer to meta data str with key == ":path" */
grpc_mdstr *path_str; /* pointer to meta data str with key == ":path" */
} channel_data;
static void extract_and_annotate_method_tag(grpc_stream_op_buffer* sopb,
call_data* calld,
channel_data* chand) {
grpc_linked_mdelem* m;
static void extract_and_annotate_method_tag(grpc_stream_op_buffer *sopb,
call_data *calld,
channel_data *chand) {
grpc_linked_mdelem *m;
size_t i;
for (i = 0; i < sopb->nops; i++) {
grpc_stream_op* op = &sopb->ops[i];
grpc_stream_op *op = &sopb->ops[i];
if (op->type != GRPC_OP_METADATA) continue;
for (m = op->data.metadata.list.head; m != NULL; m = m->next) {
if (m->md->key == chand->path_str) {
gpr_log(GPR_DEBUG, "%s",
(const char*)GPR_SLICE_START_PTR(m->md->value->slice));
(const char *)GPR_SLICE_START_PTR(m->md->value->slice));
/* Add method tag here */
}
}
}
}
static void client_mutate_op(grpc_call_element* elem,
grpc_transport_stream_op* op) {
call_data* calld = elem->call_data;
channel_data* chand = elem->channel_data;
static void client_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
if (op->send_ops) {
extract_and_annotate_method_tag(op->send_ops, calld, chand);
}
}
static void client_start_transport_op(grpc_call_element* elem,
grpc_transport_stream_op* op) {
static void client_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
client_mutate_op(elem, op);
grpc_call_next_op(elem, op);
grpc_call_next_op(exec_ctx, elem, op);
}
static void server_on_done_recv(void* ptr, int success) {
grpc_call_element* elem = ptr;
call_data* calld = elem->call_data;
channel_data* chand = elem->channel_data;
static void server_on_done_recv(grpc_exec_ctx *exec_ctx, void *ptr,
int success) {
grpc_call_element *elem = ptr;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
if (success) {
extract_and_annotate_method_tag(calld->recv_ops, calld, chand);
}
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
}
static void server_mutate_op(grpc_call_element* elem,
grpc_transport_stream_op* op) {
call_data* calld = elem->call_data;
static void server_mutate_op(grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
if (op->recv_ops) {
/* substitute our callback for the op callback */
calld->recv_ops = op->recv_ops;
@ -115,56 +117,63 @@ static void server_mutate_op(grpc_call_element* elem,
}
}
static void server_start_transport_op(grpc_call_element* elem,
grpc_transport_stream_op* op) {
call_data* calld = elem->call_data;
static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
GPR_ASSERT((calld->op_id.upper != 0) || (calld->op_id.lower != 0));
server_mutate_op(elem, op);
grpc_call_next_op(elem, op);
grpc_call_next_op(exec_ctx, elem, op);
}
static void client_init_call_elem(grpc_call_element* elem,
const void* server_transport_data,
grpc_transport_stream_op* initial_op) {
call_data* d = elem->call_data;
static void client_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
if (initial_op) client_mutate_op(elem, initial_op);
}
static void client_destroy_call_elem(grpc_call_element* elem) {
call_data* d = elem->call_data;
static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc client stats and census_rpc_end_op here */
}
static void server_init_call_elem(grpc_call_element* elem,
const void* server_transport_data,
grpc_transport_stream_op* initial_op) {
call_data* d = elem->call_data;
static void server_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
d->start_ts = gpr_now(GPR_CLOCK_REALTIME);
/* TODO(hongyu): call census_tracing_start_op here. */
grpc_iomgr_closure_init(d->on_done_recv, server_on_done_recv, elem);
grpc_closure_init(d->on_done_recv, server_on_done_recv, elem);
if (initial_op) server_mutate_op(elem, initial_op);
}
static void server_destroy_call_elem(grpc_call_element* elem) {
call_data* d = elem->call_data;
static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
call_data *d = elem->call_data;
GPR_ASSERT(d != NULL);
/* TODO(hongyu): record rpc server stats and census_tracing_end_op here */
}
static void init_channel_elem(grpc_channel_element* elem, grpc_channel* master,
const grpc_channel_args* args, grpc_mdctx* mdctx,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
channel_data* chand = elem->channel_data;
channel_data *chand = elem->channel_data;
GPR_ASSERT(chand != NULL);
chand->path_str = grpc_mdstr_from_string(mdctx, ":path", 0);
}
static void destroy_channel_elem(grpc_channel_element* elem) {
channel_data* chand = elem->channel_data;
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
GPR_ASSERT(chand != NULL);
if (chand->path_str != NULL) {
GRPC_MDSTR_UNREF(chand->path_str);

@ -151,8 +151,8 @@ grpc_channel_args *grpc_channel_args_set_compression_algorithm(
/** Returns 1 if the argument for compression algorithm's enabled states bitset
* was found in \a a, returning the arg's value in \a states. Otherwise, returns
* 0. */
static int find_compression_algorithm_states_bitset(
const grpc_channel_args *a, int **states_arg) {
static int find_compression_algorithm_states_bitset(const grpc_channel_args *a,
int **states_arg) {
if (a != NULL) {
size_t i;
for (i = 0; i < a->num_args; ++i) {
@ -167,9 +167,7 @@ static int find_compression_algorithm_states_bitset(
}
grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
grpc_channel_args **a,
grpc_compression_algorithm algorithm,
int state) {
grpc_channel_args **a, grpc_compression_algorithm algorithm, int state) {
int *states_arg;
grpc_channel_args *result = *a;
const int states_arg_found =

@ -75,9 +75,7 @@ grpc_channel_args *grpc_channel_args_set_compression_algorithm(
* modified to point to the returned instance (which may be different from the
* input value of \a a). */
grpc_channel_args *grpc_channel_args_compression_algorithm_set_state(
grpc_channel_args **a,
grpc_compression_algorithm algorithm,
int enabled);
grpc_channel_args **a, grpc_compression_algorithm algorithm, int enabled);
/** Returns the bitset representing the support state (true for enabled, false
* for disabled) for compression algorithms.

@ -101,7 +101,8 @@ grpc_call_element *grpc_call_stack_element(grpc_call_stack *call_stack,
return CALL_ELEMS_FROM_STACK(call_stack) + index;
}
void grpc_channel_stack_init(const grpc_channel_filter **filters,
void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
const grpc_channel_filter **filters,
size_t filter_count, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context,
@ -123,7 +124,7 @@ void grpc_channel_stack_init(const grpc_channel_filter **filters,
for (i = 0; i < filter_count; i++) {
elems[i].filter = filters[i];
elems[i].channel_data = user_data;
elems[i].filter->init_channel_elem(&elems[i], master, args,
elems[i].filter->init_channel_elem(exec_ctx, &elems[i], master, args,
metadata_context, i == 0,
i == (filter_count - 1));
user_data += ROUND_UP_TO_ALIGNMENT_SIZE(filters[i]->sizeof_channel_data);
@ -137,18 +138,20 @@ void grpc_channel_stack_init(const grpc_channel_filter **filters,
stack->call_stack_size = call_size;
}
void grpc_channel_stack_destroy(grpc_channel_stack *stack) {
void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
grpc_channel_stack *stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(stack);
size_t count = stack->count;
size_t i;
/* destroy per-filter data */
for (i = 0; i < count; i++) {
channel_elems[i].filter->destroy_channel_elem(&channel_elems[i]);
channel_elems[i].filter->destroy_channel_elem(exec_ctx, &channel_elems[i]);
}
}
void grpc_call_stack_init(grpc_channel_stack *channel_stack,
void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
grpc_channel_stack *channel_stack,
const void *transport_server_data,
grpc_transport_stream_op *initial_op,
grpc_call_stack *call_stack) {
@ -168,37 +171,40 @@ void grpc_call_stack_init(grpc_channel_stack *channel_stack,
call_elems[i].filter = channel_elems[i].filter;
call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data;
call_elems[i].filter->init_call_elem(&call_elems[i], transport_server_data,
initial_op);
call_elems[i].filter->init_call_elem(exec_ctx, &call_elems[i],
transport_server_data, initial_op);
user_data +=
ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data);
}
}
void grpc_call_stack_destroy(grpc_call_stack *stack) {
void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack) {
grpc_call_element *elems = CALL_ELEMS_FROM_STACK(stack);
size_t count = stack->count;
size_t i;
/* destroy per-filter data */
for (i = 0; i < count; i++) {
elems[i].filter->destroy_call_elem(&elems[i]);
elems[i].filter->destroy_call_elem(exec_ctx, &elems[i]);
}
}
void grpc_call_next_op(grpc_call_element *elem, grpc_transport_stream_op *op) {
void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_transport_stream_op *op) {
grpc_call_element *next_elem = elem + 1;
next_elem->filter->start_transport_stream_op(next_elem, op);
next_elem->filter->start_transport_stream_op(exec_ctx, next_elem, op);
}
char *grpc_call_next_get_peer(grpc_call_element *elem) {
char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
grpc_call_element *next_elem = elem + 1;
return next_elem->filter->get_peer(next_elem);
return next_elem->filter->get_peer(exec_ctx, next_elem);
}
void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op) {
void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_transport_op *op) {
grpc_channel_element *next_elem = elem + 1;
next_elem->filter->start_transport_op(next_elem, op);
next_elem->filter->start_transport_op(exec_ctx, next_elem, op);
}
grpc_channel_stack *grpc_channel_stack_from_top_element(
@ -212,9 +218,10 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem) {
sizeof(grpc_call_stack)));
}
void grpc_call_element_send_cancel(grpc_call_element *cur_elem) {
void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
grpc_call_element *cur_elem) {
grpc_transport_stream_op op;
memset(&op, 0, sizeof(op));
op.cancel_with_status = GRPC_STATUS_CANCELLED;
grpc_call_next_op(cur_elem, &op);
grpc_call_next_op(exec_ctx, cur_elem, &op);
}

@ -64,12 +64,14 @@ typedef struct grpc_call_element grpc_call_element;
typedef struct {
/* Called to eg. send/receive data on a call.
See grpc_call_next_op on how to call the next element in the stack */
void (*start_transport_stream_op)(grpc_call_element *elem,
void (*start_transport_stream_op)(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op);
/* Called to handle channel level operations - e.g. new calls, or transport
closure.
See grpc_channel_next_op on how to call the next element in the stack */
void (*start_transport_op)(grpc_channel_element *elem, grpc_transport_op *op);
void (*start_transport_op)(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_transport_op *op);
/* sizeof(per call data) */
size_t sizeof_call_data;
@ -80,13 +82,13 @@ typedef struct {
server_transport_data is an opaque pointer. If it is NULL, this call is
on a client; if it is non-NULL, then it points to memory owned by the
transport and is on the server. Most filters want to ignore this
argument.*/
void (*init_call_elem)(grpc_call_element *elem,
argument. */
void (*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op);
/* Destroy per call data.
The filter does not need to do any chaining */
void (*destroy_call_elem)(grpc_call_element *elem);
void (*destroy_call_elem)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
/* sizeof(per channel data) */
size_t sizeof_channel_data;
@ -96,16 +98,17 @@ typedef struct {
is_first, is_last designate this elements position in the stack, and are
useful for asserting correct configuration by upper layer code.
The filter does not need to do any chaining */
void (*init_channel_elem)(grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args,
void (*init_channel_elem)(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel *master, const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first,
int is_last);
/* Destroy per channel data.
The filter does not need to do any chaining */
void (*destroy_channel_elem)(grpc_channel_element *elem);
void (*destroy_channel_elem)(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem);
/* Implement grpc_call_get_peer() */
char *(*get_peer)(grpc_call_element *elem);
char *(*get_peer)(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
/* The name of this filter */
const char *name;
@ -153,31 +156,36 @@ grpc_call_element *grpc_call_stack_element(grpc_call_stack *stack, size_t i);
size_t grpc_channel_stack_size(const grpc_channel_filter **filters,
size_t filter_count);
/* Initialize a channel stack given some filters */
void grpc_channel_stack_init(const grpc_channel_filter **filters,
void grpc_channel_stack_init(grpc_exec_ctx *exec_ctx,
const grpc_channel_filter **filters,
size_t filter_count, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context,
grpc_channel_stack *stack);
/* Destroy a channel stack */
void grpc_channel_stack_destroy(grpc_channel_stack *stack);
void grpc_channel_stack_destroy(grpc_exec_ctx *exec_ctx,
grpc_channel_stack *stack);
/* Initialize a call stack given a channel stack. transport_server_data is
expected to be NULL on a client, or an opaque transport owned pointer on the
server. */
void grpc_call_stack_init(grpc_channel_stack *channel_stack,
void grpc_call_stack_init(grpc_exec_ctx *exec_ctx,
grpc_channel_stack *channel_stack,
const void *transport_server_data,
grpc_transport_stream_op *initial_op,
grpc_call_stack *call_stack);
/* Destroy a call stack */
void grpc_call_stack_destroy(grpc_call_stack *stack);
void grpc_call_stack_destroy(grpc_exec_ctx *exec_ctx, grpc_call_stack *stack);
/* Call the next operation in a call stack */
void grpc_call_next_op(grpc_call_element *elem, grpc_transport_stream_op *op);
void grpc_call_next_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_transport_stream_op *op);
/* Call the next operation (depending on call directionality) in a channel
stack */
void grpc_channel_next_op(grpc_channel_element *elem, grpc_transport_op *op);
void grpc_channel_next_op(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_transport_op *op);
/* Pass through a request to get_peer to the next child element */
char *grpc_call_next_get_peer(grpc_call_element *elem);
char *grpc_call_next_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
/* Given the top element of a channel stack, get the channel stack itself */
grpc_channel_stack *grpc_channel_stack_from_top_element(
@ -188,7 +196,8 @@ grpc_call_stack *grpc_call_stack_from_top_element(grpc_call_element *elem);
void grpc_call_log_op(char *file, int line, gpr_log_severity severity,
grpc_call_element *elem, grpc_transport_stream_op *op);
void grpc_call_element_send_cancel(grpc_call_element *cur_elem);
void grpc_call_element_send_cancel(grpc_exec_ctx *exec_ctx,
grpc_call_element *cur_elem);
extern int grpc_trace_channel;

@ -73,9 +73,9 @@ typedef struct {
guarded by mu_config */
grpc_client_config *incoming_configuration;
/** a list of closures that are all waiting for config to come in */
grpc_iomgr_closure *waiting_for_config_closures;
grpc_closure_list waiting_for_config_closures;
/** resolver callback */
grpc_iomgr_closure on_config_changed;
grpc_closure on_config_changed;
/** connectivity state being tracked */
grpc_connectivity_state_tracker state_tracker;
/** when an lb_policy arrives, should we try to exit idle */
@ -91,7 +91,7 @@ typedef struct {
update the channel, and create a new watcher */
typedef struct {
channel_data *chand;
grpc_iomgr_closure on_changed;
grpc_closure on_changed;
grpc_connectivity_state state;
grpc_lb_policy *lb_policy;
} lb_policy_connectivity_watcher;
@ -115,7 +115,7 @@ struct call_data {
call_state state;
gpr_timespec deadline;
grpc_subchannel *picked_channel;
grpc_iomgr_closure async_setup_task;
grpc_closure async_setup_task;
grpc_transport_stream_op waiting_op;
/* our child call stack */
grpc_subchannel_call *subchannel_call;
@ -123,17 +123,18 @@ struct call_data {
grpc_linked_mdelem details;
};
static grpc_iomgr_closure *merge_into_waiting_op(
grpc_call_element *elem,
grpc_transport_stream_op *new_op) GRPC_MUST_USE_RESULT;
static grpc_closure *merge_into_waiting_op(grpc_call_element *elem,
grpc_transport_stream_op *new_op)
GRPC_MUST_USE_RESULT;
static void handle_op_after_cancellation(grpc_call_element *elem,
static void handle_op_after_cancellation(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
if (op->send_ops) {
grpc_stream_ops_unref_owned_objects(op->send_ops->ops, op->send_ops->nops);
op->on_done_send->cb(op->on_done_send->cb_arg, 0);
op->on_done_send->cb(exec_ctx, op->on_done_send->cb_arg, 0);
}
if (op->recv_ops) {
char status[GPR_LTOA_MIN_BUFSIZE];
@ -152,26 +153,28 @@ static void handle_op_after_cancellation(grpc_call_element *elem,
mdb.deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
grpc_sopb_add_metadata(op->recv_ops, mdb);
*op->recv_state = GRPC_STREAM_CLOSED;
op->on_done_recv->cb(op->on_done_recv->cb_arg, 1);
op->on_done_recv->cb(exec_ctx, op->on_done_recv->cb_arg, 1);
}
if (op->on_consumed) {
op->on_consumed->cb(op->on_consumed->cb_arg, 0);
op->on_consumed->cb(exec_ctx, op->on_consumed->cb_arg, 0);
}
}
typedef struct {
grpc_iomgr_closure closure;
grpc_closure closure;
grpc_call_element *elem;
} waiting_call;
static void perform_transport_stream_op(grpc_call_element *elem,
static void perform_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op,
int continuation);
static void continue_with_pick(void *arg, int iomgr_success) {
static void continue_with_pick(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
waiting_call *wc = arg;
call_data *calld = wc->elem->call_data;
perform_transport_stream_op(wc->elem, &calld->waiting_op, 1);
perform_transport_stream_op(exec_ctx, wc->elem, &calld->waiting_op, 1);
gpr_free(wc);
}
@ -179,10 +182,9 @@ static void add_to_lb_policy_wait_queue_locked_state_config(
grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
waiting_call *wc = gpr_malloc(sizeof(*wc));
grpc_iomgr_closure_init(&wc->closure, continue_with_pick, wc);
grpc_closure_init(&wc->closure, continue_with_pick, wc);
wc->elem = elem;
wc->closure.next = chand->waiting_for_config_closures;
chand->waiting_for_config_closures = &wc->closure;
grpc_closure_list_add(&chand->waiting_for_config_closures, &wc->closure, 1);
}
static int is_empty(void *p, int len) {
@ -194,7 +196,8 @@ static int is_empty(void *p, int len) {
return 1;
}
static void started_call(void *arg, int iomgr_success) {
static void started_call(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
call_data *calld = arg;
grpc_transport_stream_op op;
int have_waiting;
@ -204,21 +207,21 @@ static void started_call(void *arg, int iomgr_success) {
memset(&op, 0, sizeof(op));
op.cancel_with_status = GRPC_STATUS_CANCELLED;
gpr_mu_unlock(&calld->mu_state);
grpc_subchannel_call_process_op(calld->subchannel_call, &op);
grpc_subchannel_call_process_op(exec_ctx, calld->subchannel_call, &op);
} else if (calld->state == CALL_WAITING_FOR_CALL) {
have_waiting = !is_empty(&calld->waiting_op, sizeof(calld->waiting_op));
if (calld->subchannel_call != NULL) {
calld->state = CALL_ACTIVE;
gpr_mu_unlock(&calld->mu_state);
if (have_waiting) {
grpc_subchannel_call_process_op(calld->subchannel_call,
grpc_subchannel_call_process_op(exec_ctx, calld->subchannel_call,
&calld->waiting_op);
}
} else {
calld->state = CALL_CANCELLED;
gpr_mu_unlock(&calld->mu_state);
if (have_waiting) {
handle_op_after_cancellation(calld->elem, &calld->waiting_op);
handle_op_after_cancellation(exec_ctx, calld->elem, &calld->waiting_op);
}
}
} else {
@ -227,36 +230,37 @@ static void started_call(void *arg, int iomgr_success) {
}
}
static void picked_target(void *arg, int iomgr_success) {
static void picked_target(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
call_data *calld = arg;
grpc_pollset *pollset;
if (calld->picked_channel == NULL) {
/* treat this like a cancellation */
calld->waiting_op.cancel_with_status = GRPC_STATUS_UNAVAILABLE;
perform_transport_stream_op(calld->elem, &calld->waiting_op, 1);
perform_transport_stream_op(exec_ctx, calld->elem, &calld->waiting_op, 1);
} else {
gpr_mu_lock(&calld->mu_state);
if (calld->state == CALL_CANCELLED) {
gpr_mu_unlock(&calld->mu_state);
handle_op_after_cancellation(calld->elem, &calld->waiting_op);
handle_op_after_cancellation(exec_ctx, calld->elem, &calld->waiting_op);
} else {
GPR_ASSERT(calld->state == CALL_WAITING_FOR_PICK);
calld->state = CALL_WAITING_FOR_CALL;
pollset = calld->waiting_op.bind_pollset;
gpr_mu_unlock(&calld->mu_state);
grpc_iomgr_closure_init(&calld->async_setup_task, started_call, calld);
grpc_subchannel_create_call(calld->picked_channel, pollset,
grpc_closure_init(&calld->async_setup_task, started_call, calld);
grpc_subchannel_create_call(exec_ctx, calld->picked_channel, pollset,
&calld->subchannel_call,
&calld->async_setup_task);
}
}
}
static grpc_iomgr_closure *merge_into_waiting_op(
grpc_call_element *elem, grpc_transport_stream_op *new_op) {
static grpc_closure *merge_into_waiting_op(grpc_call_element *elem,
grpc_transport_stream_op *new_op) {
call_data *calld = elem->call_data;
grpc_iomgr_closure *consumed_op = NULL;
grpc_closure *consumed_op = NULL;
grpc_transport_stream_op *waiting_op = &calld->waiting_op;
GPR_ASSERT((waiting_op->send_ops != NULL) + (new_op->send_ops != NULL) <= 1);
GPR_ASSERT((waiting_op->recv_ops != NULL) + (new_op->recv_ops != NULL) <= 1);
@ -282,7 +286,7 @@ static grpc_iomgr_closure *merge_into_waiting_op(
return consumed_op;
}
static char *cc_get_peer(grpc_call_element *elem) {
static char *cc_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
grpc_subchannel_call *subchannel_call;
@ -293,8 +297,8 @@ static char *cc_get_peer(grpc_call_element *elem) {
subchannel_call = calld->subchannel_call;
GRPC_SUBCHANNEL_CALL_REF(subchannel_call, "get_peer");
gpr_mu_unlock(&calld->mu_state);
result = grpc_subchannel_call_get_peer(subchannel_call);
GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "get_peer");
result = grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, subchannel_call, "get_peer");
return result;
} else {
gpr_mu_unlock(&calld->mu_state);
@ -302,7 +306,8 @@ static char *cc_get_peer(grpc_call_element *elem) {
}
}
static void perform_transport_stream_op(grpc_call_element *elem,
static void perform_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op,
int continuation) {
call_data *calld = elem->call_data;
@ -310,7 +315,6 @@ static void perform_transport_stream_op(grpc_call_element *elem,
grpc_subchannel_call *subchannel_call;
grpc_lb_policy *lb_policy;
grpc_transport_stream_op op2;
grpc_iomgr_closure *consumed_op = NULL;
GPR_ASSERT(elem->filter == &grpc_client_channel_filter);
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
@ -320,15 +324,15 @@ static void perform_transport_stream_op(grpc_call_element *elem,
GPR_ASSERT(!continuation);
subchannel_call = calld->subchannel_call;
gpr_mu_unlock(&calld->mu_state);
grpc_subchannel_call_process_op(subchannel_call, op);
grpc_subchannel_call_process_op(exec_ctx, subchannel_call, op);
break;
case CALL_CANCELLED:
gpr_mu_unlock(&calld->mu_state);
handle_op_after_cancellation(elem, op);
handle_op_after_cancellation(exec_ctx, elem, op);
break;
case CALL_WAITING_FOR_SEND:
GPR_ASSERT(!continuation);
consumed_op = merge_into_waiting_op(elem, op);
grpc_exec_ctx_enqueue(exec_ctx, merge_into_waiting_op(elem, op), 1);
if (!calld->waiting_op.send_ops &&
calld->waiting_op.cancel_with_status == GRPC_STATUS_OK) {
gpr_mu_unlock(&calld->mu_state);
@ -354,10 +358,10 @@ static void perform_transport_stream_op(grpc_call_element *elem,
op2.on_consumed = NULL;
}
gpr_mu_unlock(&calld->mu_state);
handle_op_after_cancellation(elem, op);
handle_op_after_cancellation(elem, &op2);
handle_op_after_cancellation(exec_ctx, elem, op);
handle_op_after_cancellation(exec_ctx, elem, &op2);
} else {
consumed_op = merge_into_waiting_op(elem, op);
grpc_exec_ctx_enqueue(exec_ctx, merge_into_waiting_op(elem, op), 1);
gpr_mu_unlock(&calld->mu_state);
}
break;
@ -367,7 +371,7 @@ static void perform_transport_stream_op(grpc_call_element *elem,
if (op->cancel_with_status != GRPC_STATUS_OK) {
calld->state = CALL_CANCELLED;
gpr_mu_unlock(&calld->mu_state);
handle_op_after_cancellation(elem, op);
handle_op_after_cancellation(exec_ctx, elem, op);
} else {
calld->waiting_op = *op;
@ -394,20 +398,19 @@ static void perform_transport_stream_op(grpc_call_element *elem,
GPR_ASSERT(waiting_op->send_ops->ops[0].type == GRPC_OP_METADATA);
gpr_mu_unlock(&calld->mu_state);
grpc_iomgr_closure_init(&calld->async_setup_task, picked_target,
calld);
grpc_lb_policy_pick(lb_policy, bind_pollset, initial_metadata,
&calld->picked_channel,
grpc_closure_init(&calld->async_setup_task, picked_target, calld);
grpc_lb_policy_pick(exec_ctx, lb_policy, bind_pollset,
initial_metadata, &calld->picked_channel,
&calld->async_setup_task);
GRPC_LB_POLICY_UNREF(lb_policy, "pick");
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "pick");
} else if (chand->resolver != NULL) {
calld->state = CALL_WAITING_FOR_CONFIG;
add_to_lb_policy_wait_queue_locked_state_config(elem);
if (!chand->started_resolving && chand->resolver != NULL) {
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
chand->started_resolving = 1;
grpc_resolver_next(chand->resolver,
grpc_resolver_next(exec_ctx, chand->resolver,
&chand->incoming_configuration,
&chand->on_config_changed);
}
@ -417,62 +420,68 @@ static void perform_transport_stream_op(grpc_call_element *elem,
calld->state = CALL_CANCELLED;
gpr_mu_unlock(&chand->mu_config);
gpr_mu_unlock(&calld->mu_state);
handle_op_after_cancellation(elem, op);
handle_op_after_cancellation(exec_ctx, elem, op);
}
}
}
break;
}
if (consumed_op != NULL) {
consumed_op->cb(consumed_op->cb_arg, 1);
}
}
static void cc_start_transport_stream_op(grpc_call_element *elem,
static void cc_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
perform_transport_stream_op(elem, op, 0);
perform_transport_stream_op(exec_ctx, elem, op, 0);
}
static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy,
static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
grpc_lb_policy *lb_policy,
grpc_connectivity_state current_state);
static void on_lb_policy_state_changed(void *arg, int iomgr_success) {
static void on_lb_policy_state_changed_locked(
grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
/* check if the notification is for a stale policy */
if (w->lb_policy != w->chand->lb_policy) return;
grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, w->state,
"lb_changed");
if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
}
}
static void on_lb_policy_state_changed(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
lb_policy_connectivity_watcher *w = arg;
gpr_mu_lock(&w->chand->mu_config);
/* check if the notification is for a stale policy */
if (w->lb_policy == w->chand->lb_policy) {
grpc_connectivity_state_set(&w->chand->state_tracker, w->state,
"lb_changed");
if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
watch_lb_policy(w->chand, w->lb_policy, w->state);
}
}
on_lb_policy_state_changed_locked(exec_ctx, w);
gpr_mu_unlock(&w->chand->mu_config);
GRPC_CHANNEL_INTERNAL_UNREF(w->chand->master, "watch_lb_policy");
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, w->chand->master, "watch_lb_policy");
gpr_free(w);
}
static void watch_lb_policy(channel_data *chand, grpc_lb_policy *lb_policy,
static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
grpc_lb_policy *lb_policy,
grpc_connectivity_state current_state) {
lb_policy_connectivity_watcher *w = gpr_malloc(sizeof(*w));
GRPC_CHANNEL_INTERNAL_REF(chand->master, "watch_lb_policy");
w->chand = chand;
grpc_iomgr_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
grpc_closure_init(&w->on_changed, on_lb_policy_state_changed, w);
w->state = current_state;
w->lb_policy = lb_policy;
grpc_lb_policy_notify_on_state_change(lb_policy, &w->state, &w->on_changed);
grpc_lb_policy_notify_on_state_change(exec_ctx, lb_policy, &w->state,
&w->on_changed);
}
static void cc_on_config_changed(void *arg, int iomgr_success) {
static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
channel_data *chand = arg;
grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy;
grpc_resolver *old_resolver;
grpc_iomgr_closure *wakeup_closures = NULL;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
int exit_idle = 0;
@ -481,10 +490,10 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
if (lb_policy != NULL) {
GRPC_LB_POLICY_REF(lb_policy, "channel");
GRPC_LB_POLICY_REF(lb_policy, "config_change");
state = grpc_lb_policy_check_connectivity(lb_policy);
state = grpc_lb_policy_check_connectivity(exec_ctx, lb_policy);
}
grpc_client_config_unref(chand->incoming_configuration);
grpc_client_config_unref(exec_ctx, chand->incoming_configuration);
}
chand->incoming_configuration = NULL;
@ -493,8 +502,7 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy;
if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) {
wakeup_closures = chand->waiting_for_config_closures;
chand->waiting_for_config_closures = NULL;
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures);
}
if (lb_policy != NULL && chand->exit_idle_when_lb_policy_arrives) {
GRPC_LB_POLICY_REF(lb_policy, "exit_idle");
@ -505,57 +513,53 @@ static void cc_on_config_changed(void *arg, int iomgr_success) {
if (iomgr_success && chand->resolver) {
grpc_resolver *resolver = chand->resolver;
GRPC_RESOLVER_REF(resolver, "channel-next");
grpc_connectivity_state_set(&chand->state_tracker, state,
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
"new_lb+resolver");
if (lb_policy != NULL) {
watch_lb_policy(exec_ctx, chand, lb_policy, state);
}
gpr_mu_unlock(&chand->mu_config);
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
grpc_resolver_next(resolver, &chand->incoming_configuration,
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
&chand->on_config_changed);
GRPC_RESOLVER_UNREF(resolver, "channel-next");
if (lb_policy != NULL) {
watch_lb_policy(chand, lb_policy, state);
}
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
} else {
old_resolver = chand->resolver;
chand->resolver = NULL;
grpc_connectivity_state_set(&chand->state_tracker,
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
gpr_mu_unlock(&chand->mu_config);
if (old_resolver != NULL) {
grpc_resolver_shutdown(old_resolver);
GRPC_RESOLVER_UNREF(old_resolver, "channel");
grpc_resolver_shutdown(exec_ctx, old_resolver);
GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
}
}
if (exit_idle) {
grpc_lb_policy_exit_idle(lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "exit_idle");
grpc_lb_policy_exit_idle(exec_ctx, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "exit_idle");
}
if (old_lb_policy != NULL) {
grpc_lb_policy_shutdown(old_lb_policy);
GRPC_LB_POLICY_UNREF(old_lb_policy, "channel");
}
while (wakeup_closures) {
grpc_iomgr_closure *next = wakeup_closures->next;
wakeup_closures->cb(wakeup_closures->cb_arg, 1);
wakeup_closures = next;
grpc_lb_policy_shutdown(exec_ctx, old_lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, old_lb_policy, "channel");
}
if (lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(lb_policy, "config_change");
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "config_change");
}
GRPC_CHANNEL_INTERNAL_UNREF(chand->master, "resolver");
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, chand->master, "resolver");
}
static void cc_start_transport_op(grpc_channel_element *elem,
static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_transport_op *op) {
grpc_lb_policy *lb_policy = NULL;
channel_data *chand = elem->channel_data;
grpc_resolver *destroy_resolver = NULL;
grpc_iomgr_closure *on_consumed = op->on_consumed;
op->on_consumed = NULL;
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, 1);
GPR_ASSERT(op->set_accept_stream == NULL);
GPR_ASSERT(op->bind_pollset == NULL);
@ -563,7 +567,7 @@ static void cc_start_transport_op(grpc_channel_element *elem,
gpr_mu_lock(&chand->mu_config);
if (op->on_connectivity_state_change != NULL) {
grpc_connectivity_state_notify_on_state_change(
&chand->state_tracker, op->connectivity_state,
exec_ctx, &chand->state_tracker, op->connectivity_state,
op->on_connectivity_state_change);
op->on_connectivity_state_change = NULL;
op->connectivity_state = NULL;
@ -577,35 +581,31 @@ static void cc_start_transport_op(grpc_channel_element *elem,
}
if (op->disconnect && chand->resolver != NULL) {
grpc_connectivity_state_set(&chand->state_tracker,
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
destroy_resolver = chand->resolver;
chand->resolver = NULL;
if (chand->lb_policy != NULL) {
grpc_lb_policy_shutdown(chand->lb_policy);
GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
grpc_lb_policy_shutdown(exec_ctx, chand->lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
chand->lb_policy = NULL;
}
}
gpr_mu_unlock(&chand->mu_config);
if (destroy_resolver) {
grpc_resolver_shutdown(destroy_resolver);
GRPC_RESOLVER_UNREF(destroy_resolver, "channel");
grpc_resolver_shutdown(exec_ctx, destroy_resolver);
GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
}
if (lb_policy) {
grpc_lb_policy_broadcast(lb_policy, op);
GRPC_LB_POLICY_UNREF(lb_policy, "broadcast");
}
if (on_consumed) {
grpc_iomgr_add_callback(on_consumed);
grpc_lb_policy_broadcast(exec_ctx, lb_policy, op);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "broadcast");
}
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *calld = elem->call_data;
@ -622,7 +622,8 @@ static void init_call_elem(grpc_call_element *elem,
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
call_data *calld = elem->call_data;
grpc_subchannel_call *subchannel_call;
@ -634,7 +635,7 @@ static void destroy_call_elem(grpc_call_element *elem) {
case CALL_ACTIVE:
subchannel_call = calld->subchannel_call;
gpr_mu_unlock(&calld->mu_state);
GRPC_SUBCHANNEL_CALL_UNREF(subchannel_call, "client_channel");
GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, subchannel_call, "client_channel");
break;
case CALL_CREATED:
case CALL_CANCELLED:
@ -651,7 +652,8 @@ static void destroy_call_elem(grpc_call_element *elem) {
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args,
grpc_mdctx *metadata_context, int is_first,
int is_last) {
@ -666,25 +668,25 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
chand->mdctx = metadata_context;
chand->master = master;
grpc_pollset_set_init(&chand->pollset_set);
grpc_iomgr_closure_init(&chand->on_config_changed, cc_on_config_changed,
chand);
grpc_closure_init(&chand->on_config_changed, cc_on_config_changed, chand);
grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE,
"client_channel");
}
/* Destructor for channel_data */
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *chand = elem->channel_data;
if (chand->resolver != NULL) {
grpc_resolver_shutdown(chand->resolver);
GRPC_RESOLVER_UNREF(chand->resolver, "channel");
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
}
if (chand->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(chand->lb_policy, "channel");
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
}
grpc_connectivity_state_destroy(&chand->state_tracker);
grpc_connectivity_state_destroy(exec_ctx, &chand->state_tracker);
grpc_pollset_set_destroy(&chand->pollset_set);
gpr_mu_destroy(&chand->mu_config);
}
@ -702,7 +704,8 @@ const grpc_channel_filter grpc_client_channel_filter = {
"client-channel",
};
void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack,
void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
grpc_channel_stack *channel_stack,
grpc_resolver *resolver) {
/* post construction initialization: set the transport setup pointer */
grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
@ -711,31 +714,32 @@ void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack,
GPR_ASSERT(!chand->resolver);
chand->resolver = resolver;
GRPC_RESOLVER_REF(resolver, "channel");
if (chand->waiting_for_config_closures != NULL ||
if (!grpc_closure_list_empty(chand->waiting_for_config_closures) ||
chand->exit_idle_when_lb_policy_arrives) {
chand->started_resolving = 1;
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
grpc_resolver_next(resolver, &chand->incoming_configuration,
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
&chand->on_config_changed);
}
gpr_mu_unlock(&chand->mu_config);
}
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_channel_element *elem, int try_to_connect) {
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect) {
channel_data *chand = elem->channel_data;
grpc_connectivity_state out;
gpr_mu_lock(&chand->mu_config);
out = grpc_connectivity_state_check(&chand->state_tracker);
if (out == GRPC_CHANNEL_IDLE && try_to_connect) {
if (chand->lb_policy != NULL) {
grpc_lb_policy_exit_idle(chand->lb_policy);
grpc_lb_policy_exit_idle(exec_ctx, chand->lb_policy);
} else {
chand->exit_idle_when_lb_policy_arrives = 1;
if (!chand->started_resolving && chand->resolver != NULL) {
GRPC_CHANNEL_INTERNAL_REF(chand->master, "resolver");
chand->started_resolving = 1;
grpc_resolver_next(chand->resolver, &chand->incoming_configuration,
grpc_resolver_next(exec_ctx, chand->resolver,
&chand->incoming_configuration,
&chand->on_config_changed);
}
}
@ -745,12 +749,12 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state(
}
void grpc_client_channel_watch_connectivity_state(
grpc_channel_element *elem, grpc_connectivity_state *state,
grpc_iomgr_closure *on_complete) {
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_connectivity_state *state, grpc_closure *on_complete) {
channel_data *chand = elem->channel_data;
gpr_mu_lock(&chand->mu_config);
grpc_connectivity_state_notify_on_state_change(&chand->state_tracker, state,
on_complete);
grpc_connectivity_state_notify_on_state_change(
exec_ctx, &chand->state_tracker, state, on_complete);
gpr_mu_unlock(&chand->mu_config);
}
@ -760,14 +764,16 @@ grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
return &chand->pollset_set;
}
void grpc_client_channel_add_interested_party(grpc_channel_element *elem,
void grpc_client_channel_add_interested_party(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_pollset *pollset) {
channel_data *chand = elem->channel_data;
grpc_pollset_set_add_pollset(&chand->pollset_set, pollset);
grpc_pollset_set_add_pollset(exec_ctx, &chand->pollset_set, pollset);
}
void grpc_client_channel_del_interested_party(grpc_channel_element *elem,
void grpc_client_channel_del_interested_party(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_pollset *pollset) {
channel_data *chand = elem->channel_data;
grpc_pollset_set_del_pollset(&chand->pollset_set, pollset);
grpc_pollset_set_del_pollset(exec_ctx, &chand->pollset_set, pollset);
}

@ -49,22 +49,25 @@ extern const grpc_channel_filter grpc_client_channel_filter;
/* post-construction initializer to let the client channel know which
transport setup it should cancel upon destruction, or initiate when it needs
a connection */
void grpc_client_channel_set_resolver(grpc_channel_stack *channel_stack,
void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
grpc_channel_stack *channel_stack,
grpc_resolver *resolver);
grpc_connectivity_state grpc_client_channel_check_connectivity_state(
grpc_channel_element *elem, int try_to_connect);
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
void grpc_client_channel_watch_connectivity_state(
grpc_channel_element *elem, grpc_connectivity_state *state,
grpc_iomgr_closure *on_complete);
grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_connectivity_state *state, grpc_closure *on_complete);
grpc_pollset_set *grpc_client_channel_get_connecting_pollset_set(
grpc_channel_element *elem);
void grpc_client_channel_add_interested_party(grpc_channel_element *channel,
void grpc_client_channel_add_interested_party(grpc_exec_ctx *exec_ctx,
grpc_channel_element *channel,
grpc_pollset *pollset);
void grpc_client_channel_del_interested_party(grpc_channel_element *channel,
void grpc_client_channel_del_interested_party(grpc_exec_ctx *exec_ctx,
grpc_channel_element *channel,
grpc_pollset *pollset);
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CLIENT_CHANNEL_H */

@ -48,8 +48,8 @@ typedef struct call_data {
gpr_slice_buffer slices; /**< Buffers up input slices to be compressed */
grpc_linked_mdelem compression_algorithm_storage;
grpc_linked_mdelem accept_encoding_storage;
gpr_uint32
remaining_slice_bytes; /**< Input data to be read, as per BEGIN_MESSAGE */
gpr_uint32 remaining_slice_bytes;
/**< Input data to be read, as per BEGIN_MESSAGE */
int written_initial_metadata; /**< Already processed initial md? */
/** Compression algorithm we'll try to use. It may be given by incoming
* metadata, or by the channel's default compression settings. */
@ -268,18 +268,19 @@ static void process_send_ops(grpc_call_element *elem,
- a network event (or similar) from below, to receive something
op contains type and call direction information, in addition to the data
that is being sent or received. */
static void compress_start_transport_stream_op(grpc_call_element *elem,
static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
if (op->send_ops && op->send_ops->nops > 0) {
process_send_ops(elem, op->send_ops);
}
/* pass control down the stack */
grpc_call_next_op(elem, op);
grpc_call_next_op(exec_ctx, elem, op);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
/* grab pointers to our data from the call element */
@ -298,14 +299,16 @@ static void init_call_elem(grpc_call_element *elem,
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
gpr_slice_buffer_destroy(&calld->slices);
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
channel_data *channeld = elem->channel_data;
@ -369,7 +372,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *channeld = elem->channel_data;
grpc_compression_algorithm algo_idx;

@ -61,25 +61,27 @@ typedef struct connected_channel_call_data { void *unused; } call_data;
/* Intercept a call operation and either push it directly up or translate it
into transport stream operations */
static void con_start_transport_stream_op(grpc_call_element *elem,
static void con_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
grpc_transport_perform_stream_op(chand->transport,
grpc_transport_perform_stream_op(exec_ctx, chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld), op);
}
static void con_start_transport_op(grpc_channel_element *elem,
static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_transport_op *op) {
channel_data *chand = elem->channel_data;
grpc_transport_perform_op(chand->transport, op);
grpc_transport_perform_op(exec_ctx, chand->transport, op);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *calld = elem->call_data;
@ -87,23 +89,25 @@ static void init_call_elem(grpc_call_element *elem,
int r;
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
r = grpc_transport_init_stream(chand->transport,
r = grpc_transport_init_stream(exec_ctx, chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld),
server_transport_data, initial_op);
GPR_ASSERT(r == 0);
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
grpc_transport_destroy_stream(chand->transport,
grpc_transport_destroy_stream(exec_ctx, chand->transport,
TRANSPORT_STREAM_FROM_CALL_DATA(calld));
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
channel_data *cd = (channel_data *)elem->channel_data;
@ -113,15 +117,16 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
}
/* Destructor for channel_data */
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
channel_data *cd = (channel_data *)elem->channel_data;
GPR_ASSERT(elem->filter == &grpc_connected_channel_filter);
grpc_transport_destroy(cd->transport);
grpc_transport_destroy(exec_ctx, cd->transport);
}
static char *con_get_peer(grpc_call_element *elem) {
static char *con_get_peer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
channel_data *chand = elem->channel_data;
return grpc_transport_get_peer(chand->transport);
return grpc_transport_get_peer(exec_ctx, chand->transport);
}
const grpc_channel_filter grpc_connected_channel_filter = {

@ -43,7 +43,7 @@ extern const grpc_channel_filter grpc_connected_channel_filter;
/* Post construction fixup: set the transport in the connected channel.
Must be called before any call stack using this filter is used. */
void grpc_connected_channel_bind_transport(grpc_channel_stack *channel_stack,
grpc_transport *transport);
void grpc_connected_channel_bind_transport(grpc_channel_stack* channel_stack,
grpc_transport* transport);
#endif /* GRPC_INTERNAL_CORE_CHANNEL_CONNECTED_CHANNEL_H */

@ -50,11 +50,11 @@ typedef struct call_data {
grpc_stream_op_buffer *recv_ops;
/** Closure to call when finished with the hc_on_recv hook */
grpc_iomgr_closure *on_done_recv;
grpc_closure *on_done_recv;
/** Receive closures are chained: we inject this closure as the on_done_recv
up-call on transport_op, and remember to call our on_done_recv member
after handling it. */
grpc_iomgr_closure hc_on_recv;
grpc_closure hc_on_recv;
} call_data;
typedef struct channel_data {
@ -67,16 +67,19 @@ typedef struct channel_data {
grpc_mdelem *user_agent;
} channel_data;
/* used to silence 'variable not used' warnings */
static void ignore_unused(void *ignored) {}
typedef struct {
grpc_call_element *elem;
grpc_exec_ctx *exec_ctx;
} client_recv_filter_args;
static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
client_recv_filter_args *a = user_data;
grpc_call_element *elem = a->elem;
channel_data *channeld = elem->channel_data;
if (md == channeld->status) {
return NULL;
} else if (md->key == channeld->status->key) {
grpc_call_element_send_cancel(elem);
grpc_call_element_send_cancel(a->exec_ctx, elem);
return NULL;
} else if (md->key == channeld->content_type->key) {
return NULL;
@ -84,7 +87,7 @@ static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
return md;
}
static void hc_on_recv(void *user_data, int success) {
static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, int success) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
size_t i;
@ -92,15 +95,16 @@ static void hc_on_recv(void *user_data, int success) {
grpc_stream_op *ops = calld->recv_ops->ops;
for (i = 0; i < nops; i++) {
grpc_stream_op *op = &ops[i];
client_recv_filter_args a;
if (op->type != GRPC_OP_METADATA) continue;
calld->got_initial_metadata = 1;
grpc_metadata_batch_filter(&op->data.metadata, client_recv_filter, elem);
a.elem = elem;
a.exec_ctx = exec_ctx;
grpc_metadata_batch_filter(&op->data.metadata, client_recv_filter, &a);
}
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
}
static grpc_mdelem *client_strip_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
channel_data *channeld = elem->channel_data;
@ -126,18 +130,22 @@ static void hc_mutate_op(grpc_call_element *elem,
grpc_stream_op *stream_op = &ops[i];
if (stream_op->type != GRPC_OP_METADATA) continue;
calld->sent_initial_metadata = 1;
grpc_metadata_batch_filter(&stream_op->data.metadata, client_strip_filter, elem);
grpc_metadata_batch_filter(&stream_op->data.metadata, client_strip_filter,
elem);
/* Send : prefixed headers, which have to be before any application
layer headers. */
grpc_metadata_batch_add_head(&stream_op->data.metadata, &calld->method,
GRPC_MDELEM_REF(channeld->method));
grpc_metadata_batch_add_head(&stream_op->data.metadata, &calld->scheme,
GRPC_MDELEM_REF(channeld->scheme));
grpc_metadata_batch_add_tail(&stream_op->data.metadata, &calld->te_trailers,
grpc_metadata_batch_add_tail(&stream_op->data.metadata,
&calld->te_trailers,
GRPC_MDELEM_REF(channeld->te_trailers));
grpc_metadata_batch_add_tail(&stream_op->data.metadata, &calld->content_type,
grpc_metadata_batch_add_tail(&stream_op->data.metadata,
&calld->content_type,
GRPC_MDELEM_REF(channeld->content_type));
grpc_metadata_batch_add_tail(&stream_op->data.metadata, &calld->user_agent,
grpc_metadata_batch_add_tail(&stream_op->data.metadata,
&calld->user_agent,
GRPC_MDELEM_REF(channeld->user_agent));
break;
}
@ -151,34 +159,29 @@ static void hc_mutate_op(grpc_call_element *elem,
}
}
static void hc_start_transport_op(grpc_call_element *elem,
static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
hc_mutate_op(elem, op);
grpc_call_next_op(elem, op);
grpc_call_next_op(exec_ctx, elem, op);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
call_data *calld = elem->call_data;
calld->sent_initial_metadata = 0;
calld->got_initial_metadata = 0;
calld->on_done_recv = NULL;
grpc_iomgr_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
if (initial_op) hc_mutate_op(elem, initial_op);
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
ignore_unused(calld);
ignore_unused(channeld);
}
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {}
static const char *scheme_from_args(const grpc_channel_args *args) {
unsigned i;
@ -243,7 +246,8 @@ static grpc_mdstr *user_agent_from_args(grpc_mdctx *mdctx,
}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *channel_args,
grpc_mdctx *mdctx, int is_first, int is_last) {
/* grab pointers to our data from the channel element */
@ -268,7 +272,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data;

@ -50,11 +50,11 @@ typedef struct call_data {
grpc_stream_op_buffer *recv_ops;
/** Closure to call when finished with the hs_on_recv hook */
grpc_iomgr_closure *on_done_recv;
grpc_closure *on_done_recv;
/** Receive closures are chained: we inject this closure as the on_done_recv
up-call on transport_op, and remember to call our on_done_recv member
after handling it. */
grpc_iomgr_closure hs_on_recv;
grpc_closure hs_on_recv;
} call_data;
typedef struct channel_data {
@ -74,8 +74,14 @@ typedef struct channel_data {
grpc_mdctx *mdctx;
} channel_data;
typedef struct {
grpc_call_element *elem;
grpc_exec_ctx *exec_ctx;
} server_filter_args;
static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element *elem = user_data;
server_filter_args *a = user_data;
grpc_call_element *elem = a->elem;
channel_data *channeld = elem->channel_data;
call_data *calld = elem->call_data;
@ -117,7 +123,7 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
/* swallow it and error everything out. */
/* TODO(klempner): We ought to generate more descriptive error messages
on the wire here. */
grpc_call_element_send_cancel(elem);
grpc_call_element_send_cancel(a->exec_ctx, elem);
return NULL;
} else if (md->key == channeld->path_key) {
if (calld->seen_path) {
@ -143,7 +149,7 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
}
}
static void hs_on_recv(void *user_data, int success) {
static void hs_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, int success) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
if (success) {
@ -152,9 +158,12 @@ static void hs_on_recv(void *user_data, int success) {
grpc_stream_op *ops = calld->recv_ops->ops;
for (i = 0; i < nops; i++) {
grpc_stream_op *op = &ops[i];
server_filter_args a;
if (op->type != GRPC_OP_METADATA) continue;
calld->got_initial_metadata = 1;
grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
a.elem = elem;
a.exec_ctx = exec_ctx;
grpc_metadata_batch_filter(&op->data.metadata, server_filter, &a);
/* Have we seen the required http2 transport headers?
(:method, :scheme, content-type, with :path and :authority covered
at the channel level right now) */
@ -179,11 +188,11 @@ static void hs_on_recv(void *user_data, int success) {
}
/* Error this call out */
success = 0;
grpc_call_element_send_cancel(elem);
grpc_call_element_send_cancel(exec_ctx, elem);
}
}
}
calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, success);
}
static void hs_mutate_op(grpc_call_element *elem,
@ -202,7 +211,8 @@ static void hs_mutate_op(grpc_call_element *elem,
calld->sent_status = 1;
grpc_metadata_batch_add_head(&stream_op->data.metadata, &calld->status,
GRPC_MDELEM_REF(channeld->status_ok));
grpc_metadata_batch_add_tail(&stream_op->data.metadata, &calld->content_type,
grpc_metadata_batch_add_tail(&stream_op->data.metadata,
&calld->content_type,
GRPC_MDELEM_REF(channeld->content_type));
break;
}
@ -216,30 +226,33 @@ static void hs_mutate_op(grpc_call_element *elem,
}
}
static void hs_start_transport_op(grpc_call_element *elem,
static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
hs_mutate_op(elem, op);
grpc_call_next_op(elem, op);
grpc_call_next_op(exec_ctx, elem, op);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
/* initialize members */
memset(calld, 0, sizeof(*calld));
grpc_iomgr_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
grpc_closure_init(&calld->hs_on_recv, hs_on_recv, elem);
if (initial_op) hs_mutate_op(elem, initial_op);
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {}
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
/* grab pointers to our data from the channel element */
@ -270,7 +283,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data;

@ -62,16 +62,17 @@ static void noop_mutate_op(grpc_call_element *elem,
- a network event (or similar) from below, to receive something
op contains type and call direction information, in addition to the data
that is being sent or received. */
static void noop_start_transport_stream_op(grpc_call_element *elem,
static void noop_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {
noop_mutate_op(elem, op);
/* pass control down the stack */
grpc_call_next_op(elem, op);
grpc_call_next_op(exec_ctx, elem, op);
}
/* Constructor for call_data */
static void init_call_elem(grpc_call_element *elem,
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const void *server_transport_data,
grpc_transport_stream_op *initial_op) {
/* grab pointers to our data from the call element */
@ -85,17 +86,12 @@ static void init_call_elem(grpc_call_element *elem,
}
/* Destructor for call_data */
static void destroy_call_elem(grpc_call_element *elem) {
/* grab pointers to our data from the call element */
call_data *calld = elem->call_data;
channel_data *channeld = elem->channel_data;
ignore_unused(calld);
ignore_unused(channeld);
}
static void destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem) {}
/* Constructor for channel_data */
static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
static void init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem, grpc_channel *master,
const grpc_channel_args *args, grpc_mdctx *mdctx,
int is_first, int is_last) {
/* grab pointers to our data from the channel element */
@ -112,7 +108,8 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
}
/* Destructor for channel data */
static void destroy_channel_elem(grpc_channel_element *elem) {
static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) {
/* grab pointers to our data from the channel element */
channel_data *channeld = elem->channel_data;

@ -51,21 +51,19 @@ grpc_client_config *grpc_client_config_create() {
void grpc_client_config_ref(grpc_client_config *c) { gpr_ref(&c->refs); }
void grpc_client_config_unref(grpc_client_config *c) {
void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) {
if (gpr_unref(&c->refs)) {
GRPC_LB_POLICY_UNREF(c->lb_policy, "client_config");
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
gpr_free(c);
}
}
void grpc_client_config_set_lb_policy(grpc_client_config *c,
grpc_lb_policy *lb_policy) {
GPR_ASSERT(c->lb_policy == NULL);
if (lb_policy) {
GRPC_LB_POLICY_REF(lb_policy, "client_config");
}
if (c->lb_policy) {
GRPC_LB_POLICY_UNREF(c->lb_policy, "client_config");
}
c->lb_policy = lb_policy;
}

@ -42,7 +42,8 @@ typedef struct grpc_client_config grpc_client_config;
grpc_client_config *grpc_client_config_create();
void grpc_client_config_ref(grpc_client_config *client_config);
void grpc_client_config_unref(grpc_client_config *client_config);
void grpc_client_config_unref(grpc_exec_ctx *exec_ctx,
grpc_client_config *client_config);
void grpc_client_config_set_lb_policy(grpc_client_config *client_config,
grpc_lb_policy *lb_policy);

@ -33,21 +33,22 @@
#include "src/core/client_config/connector.h"
void grpc_connector_ref(grpc_connector *connector) {
void grpc_connector_ref(grpc_connector* connector) {
connector->vtable->ref(connector);
}
void grpc_connector_unref(grpc_connector *connector) {
connector->vtable->unref(connector);
void grpc_connector_unref(grpc_exec_ctx* exec_ctx, grpc_connector* connector) {
connector->vtable->unref(exec_ctx, connector);
}
void grpc_connector_connect(grpc_connector *connector,
const grpc_connect_in_args *in_args,
grpc_connect_out_args *out_args,
grpc_iomgr_closure *notify) {
connector->vtable->connect(connector, in_args, out_args, notify);
void grpc_connector_connect(grpc_exec_ctx* exec_ctx, grpc_connector* connector,
const grpc_connect_in_args* in_args,
grpc_connect_out_args* out_args,
grpc_closure* notify) {
connector->vtable->connect(exec_ctx, connector, in_args, out_args, notify);
}
void grpc_connector_shutdown(grpc_connector *connector) {
connector->vtable->shutdown(connector);
void grpc_connector_shutdown(grpc_exec_ctx* exec_ctx,
grpc_connector* connector) {
connector->vtable->shutdown(exec_ctx, connector);
}

@ -55,8 +55,6 @@ typedef struct {
gpr_timespec deadline;
/** channel arguments (to be passed to transport) */
const grpc_channel_args *channel_args;
/** metadata context */
grpc_mdctx *metadata_context;
} grpc_connect_in_args;
typedef struct {
@ -69,23 +67,24 @@ typedef struct {
struct grpc_connector_vtable {
void (*ref)(grpc_connector *connector);
void (*unref)(grpc_connector *connector);
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
/** Implementation of grpc_connector_shutdown */
void (*shutdown)(grpc_connector *connector);
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
/** Implementation of grpc_connector_connect */
void (*connect)(grpc_connector *connector,
void (*connect)(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
const grpc_connect_in_args *in_args,
grpc_connect_out_args *out_args, grpc_iomgr_closure *notify);
grpc_connect_out_args *out_args, grpc_closure *notify);
};
void grpc_connector_ref(grpc_connector *connector);
void grpc_connector_unref(grpc_connector *connector);
void grpc_connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *connector);
/** Connect using the connector: max one outstanding call at a time */
void grpc_connector_connect(grpc_connector *connector,
void grpc_connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *connector,
const grpc_connect_in_args *in_args,
grpc_connect_out_args *out_args,
grpc_iomgr_closure *notify);
grpc_closure *notify);
/** Cancel any pending connection */
void grpc_connector_shutdown(grpc_connector *connector);
void grpc_connector_shutdown(grpc_exec_ctx *exec_ctx,
grpc_connector *connector);
#endif

@ -43,7 +43,7 @@ typedef struct pending_pick {
struct pending_pick *next;
grpc_pollset *pollset;
grpc_subchannel **target;
grpc_iomgr_closure *on_complete;
grpc_closure *on_complete;
} pending_pick;
typedef struct {
@ -53,7 +53,7 @@ typedef struct {
grpc_subchannel **subchannels;
size_t num_subchannels;
grpc_iomgr_closure connectivity_changed;
grpc_closure connectivity_changed;
/** mutex protecting remaining members */
gpr_mu mu;
@ -76,87 +76,92 @@ typedef struct {
grpc_connectivity_state_tracker state_tracker;
} pick_first_lb_policy;
static void del_interested_parties_locked(pick_first_lb_policy *p) {
static void del_interested_parties_locked(grpc_exec_ctx *exec_ctx,
pick_first_lb_policy *p) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_del_interested_party(p->subchannels[p->checking_subchannel],
pp->pollset);
grpc_subchannel_del_interested_party(
exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
}
}
static void add_interested_parties_locked(pick_first_lb_policy *p) {
static void add_interested_parties_locked(grpc_exec_ctx *exec_ctx,
pick_first_lb_policy *p) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel],
pp->pollset);
grpc_subchannel_add_interested_party(
exec_ctx, p->subchannels[p->checking_subchannel], pp->pollset);
}
}
void pf_destroy(grpc_lb_policy *pol) {
void pf_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
size_t i;
del_interested_parties_locked(p);
GPR_ASSERT(p->pending_picks == NULL);
for (i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(p->subchannels[i], "pick_first");
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "pick_first");
}
grpc_connectivity_state_destroy(&p->state_tracker);
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
gpr_free(p->subchannels);
gpr_mu_destroy(&p->mu);
gpr_free(p);
}
void pf_shutdown(grpc_lb_policy *pol) {
void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
gpr_mu_lock(&p->mu);
del_interested_parties_locked(p);
del_interested_parties_locked(exec_ctx, p);
p->shutdown = 1;
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
pp = p->pending_picks;
p->pending_picks = NULL;
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
gpr_mu_unlock(&p->mu);
while (pp != NULL) {
pending_pick *next = pp->next;
*pp->target = NULL;
grpc_iomgr_add_delayed_callback(pp->on_complete, 0);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
gpr_free(pp);
pp = next;
}
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_FATAL_FAILURE,
"shutdown");
gpr_mu_unlock(&p->mu);
}
static void start_picking(pick_first_lb_policy *p) {
static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
p->started_picking = 1;
p->checking_subchannel = 0;
p->checking_connectivity = GRPC_CHANNEL_IDLE;
GRPC_LB_POLICY_REF(&p->base, "pick_first_connectivity");
grpc_subchannel_notify_on_state_change(p->subchannels[p->checking_subchannel],
&p->checking_connectivity,
&p->connectivity_changed);
grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel],
&p->checking_connectivity, &p->connectivity_changed);
}
void pf_exit_idle(grpc_lb_policy *pol) {
void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
gpr_mu_lock(&p->mu);
if (!p->started_picking) {
start_picking(p);
start_picking(exec_ctx, p);
}
gpr_mu_unlock(&p->mu);
}
void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
grpc_iomgr_closure *on_complete) {
void pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
grpc_subchannel **target, grpc_closure *on_complete) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
gpr_mu_lock(&p->mu);
if (p->selected) {
gpr_mu_unlock(&p->mu);
*target = p->selected;
on_complete->cb(on_complete->cb_arg, 1);
grpc_exec_ctx_enqueue(exec_ctx, on_complete, 1);
} else {
if (!p->started_picking) {
start_picking(p);
start_picking(exec_ctx, p);
}
grpc_subchannel_add_interested_party(p->subchannels[p->checking_subchannel],
pollset);
grpc_subchannel_add_interested_party(
exec_ctx, p->subchannels[p->checking_subchannel], pollset);
pp = gpr_malloc(sizeof(*pp));
pp->next = p->pending_picks;
pp->pollset = pollset;
@ -167,105 +172,109 @@ void pf_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
}
}
static void pf_connectivity_changed(void *arg, int iomgr_success) {
static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
pick_first_lb_policy *p = arg;
pending_pick *pp;
int unref = 0;
gpr_mu_lock(&p->mu);
if (p->shutdown) {
unref = 1;
gpr_mu_unlock(&p->mu);
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
return;
} else if (p->selected != NULL) {
grpc_connectivity_state_set(&p->state_tracker, p->checking_connectivity,
"selected_changed");
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
p->checking_connectivity, "selected_changed");
if (p->checking_connectivity != GRPC_CHANNEL_FATAL_FAILURE) {
grpc_subchannel_notify_on_state_change(
p->selected, &p->checking_connectivity, &p->connectivity_changed);
grpc_subchannel_notify_on_state_change(exec_ctx, p->selected,
&p->checking_connectivity,
&p->connectivity_changed);
} else {
unref = 1;
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
}
} else {
loop:
switch (p->checking_connectivity) {
case GRPC_CHANNEL_READY:
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_READY,
"connecting_ready");
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_READY, "connecting_ready");
p->selected = p->subchannels[p->checking_subchannel];
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = p->selected;
grpc_subchannel_del_interested_party(p->selected, pp->pollset);
grpc_iomgr_add_delayed_callback(pp->on_complete, 1);
grpc_subchannel_del_interested_party(exec_ctx, p->selected,
pp->pollset);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
gpr_free(pp);
}
grpc_subchannel_notify_on_state_change(
p->selected, &p->checking_connectivity, &p->connectivity_changed);
grpc_subchannel_notify_on_state_change(exec_ctx, p->selected,
&p->checking_connectivity,
&p->connectivity_changed);
break;
case GRPC_CHANNEL_TRANSIENT_FAILURE:
grpc_connectivity_state_set(&p->state_tracker,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
del_interested_parties_locked(p);
del_interested_parties_locked(exec_ctx, p);
p->checking_subchannel =
(p->checking_subchannel + 1) % p->num_subchannels;
p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]);
add_interested_parties_locked(p);
add_interested_parties_locked(exec_ctx, p);
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
grpc_subchannel_notify_on_state_change(
p->subchannels[p->checking_subchannel], &p->checking_connectivity,
&p->connectivity_changed);
exec_ctx, p->subchannels[p->checking_subchannel],
&p->checking_connectivity, &p->connectivity_changed);
} else {
goto loop;
}
break;
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE:
grpc_connectivity_state_set(&p->state_tracker, p->checking_connectivity,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_CONNECTING,
"connecting_changed");
grpc_subchannel_notify_on_state_change(
p->subchannels[p->checking_subchannel], &p->checking_connectivity,
&p->connectivity_changed);
exec_ctx, p->subchannels[p->checking_subchannel],
&p->checking_connectivity, &p->connectivity_changed);
break;
case GRPC_CHANNEL_FATAL_FAILURE:
del_interested_parties_locked(p);
del_interested_parties_locked(exec_ctx, p);
GPR_SWAP(grpc_subchannel *, p->subchannels[p->checking_subchannel],
p->subchannels[p->num_subchannels - 1]);
p->num_subchannels--;
GRPC_SUBCHANNEL_UNREF(p->subchannels[p->num_subchannels], "pick_first");
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
"pick_first");
if (p->num_subchannels == 0) {
grpc_connectivity_state_set(&p->state_tracker,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE,
"no_more_channels");
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_iomgr_add_delayed_callback(pp->on_complete, 1);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
gpr_free(pp);
}
unref = 1;
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "pick_first_connectivity");
} else {
grpc_connectivity_state_set(&p->state_tracker,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"subchannel_failed");
p->checking_subchannel %= p->num_subchannels;
p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]);
add_interested_parties_locked(p);
add_interested_parties_locked(exec_ctx, p);
goto loop;
}
}
}
gpr_mu_unlock(&p->mu);
if (unref) {
GRPC_LB_POLICY_UNREF(&p->base, "pick_first_connectivity");
}
}
static void pf_broadcast(grpc_lb_policy *pol, grpc_transport_op *op) {
static void pf_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_transport_op *op) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
size_t i;
size_t n;
@ -281,13 +290,14 @@ static void pf_broadcast(grpc_lb_policy *pol, grpc_transport_op *op) {
gpr_mu_unlock(&p->mu);
for (i = 0; i < n; i++) {
grpc_subchannel_process_transport_op(subchannels[i], op);
GRPC_SUBCHANNEL_UNREF(subchannels[i], "pf_broadcast");
grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], op);
GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "pf_broadcast");
}
gpr_free(subchannels);
}
static grpc_connectivity_state pf_check_connectivity(grpc_lb_policy *pol) {
static grpc_connectivity_state pf_check_connectivity(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *pol) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
grpc_connectivity_state st;
gpr_mu_lock(&p->mu);
@ -296,13 +306,13 @@ static grpc_connectivity_state pf_check_connectivity(grpc_lb_policy *pol) {
return st;
}
static void pf_notify_on_state_change(grpc_lb_policy *pol,
grpc_connectivity_state *current,
grpc_iomgr_closure *notify) {
void pf_notify_on_state_change(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_connectivity_state *current,
grpc_closure *notify) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
gpr_mu_lock(&p->mu);
grpc_connectivity_state_notify_on_state_change(&p->state_tracker, current,
notify);
grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
current, notify);
gpr_mu_unlock(&p->mu);
}
@ -325,13 +335,14 @@ static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
GPR_ASSERT(args->num_subchannels > 0);
memset(p, 0, sizeof(*p));
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
p->subchannels =
gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
p->num_subchannels = args->num_subchannels;
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
"pick_first");
memcpy(p->subchannels, args->subchannels,
sizeof(grpc_subchannel *) * args->num_subchannels);
grpc_iomgr_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
grpc_closure_init(&p->connectivity_changed, pf_connectivity_changed, p);
gpr_mu_init(&p->mu);
return &p->base;
}

@ -47,7 +47,7 @@ typedef struct pending_pick {
struct pending_pick *next;
grpc_pollset *pollset;
grpc_subchannel **target;
grpc_iomgr_closure *on_complete;
grpc_closure *on_complete;
} pending_pick;
/** List of subchannels in a connectivity READY state */
@ -59,7 +59,7 @@ typedef struct ready_list {
typedef struct {
size_t subchannel_idx; /**< Index over p->subchannels */
void *p; /**< round_robin_lb_policy instance */
void *p; /**< round_robin_lb_policy instance */
} connectivity_changed_cb_arg;
typedef struct {
@ -72,7 +72,7 @@ typedef struct {
/** Callbacks, one per subchannel being watched, to be called when their
* respective connectivity changes */
grpc_iomgr_closure *connectivity_changed_cbs;
grpc_closure *connectivity_changed_cbs;
connectivity_changed_cb_arg *cb_args;
/** mutex protecting remaining members */
@ -160,8 +160,7 @@ static ready_list *add_connected_sc_locked(round_robin_lb_policy *p,
p->ready_list.prev = new_elem;
}
if (grpc_lb_round_robin_trace) {
gpr_log(GPR_DEBUG,
"[READYLIST] ADDING NODE %p (SC %p)", new_elem, csc);
gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (SC %p)", new_elem, csc);
}
return new_elem;
}
@ -201,30 +200,30 @@ static void remove_disconnected_sc_locked(round_robin_lb_policy *p,
gpr_free(node);
}
static void del_interested_parties_locked(round_robin_lb_policy *p,
static void del_interested_parties_locked(grpc_exec_ctx *exec_ctx,
round_robin_lb_policy *p,
const size_t subchannel_idx) {
pending_pick *pp;
for (pp = p->pending_picks; pp; pp = pp->next) {
grpc_subchannel_del_interested_party(p->subchannels[subchannel_idx],
pp->pollset);
grpc_subchannel_del_interested_party(
exec_ctx, p->subchannels[subchannel_idx], pp->pollset);
}
}
void rr_destroy(grpc_lb_policy *pol) {
void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
size_t i;
ready_list *elem;
for (i = 0; i < p->num_subchannels; i++) {
del_interested_parties_locked(p, i);
del_interested_parties_locked(exec_ctx, p, i);
}
for (i = 0; i < p->num_subchannels; i++) {
GRPC_SUBCHANNEL_UNREF(p->subchannels[i], "round_robin");
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[i], "round_robin");
}
gpr_free(p->connectivity_changed_cbs);
gpr_free(p->subchannel_connectivity);
grpc_connectivity_state_destroy(&p->state_tracker);
grpc_connectivity_state_destroy(exec_ctx, &p->state_tracker);
gpr_free(p->subchannels);
gpr_mu_destroy(&p->mu);
@ -243,53 +242,53 @@ void rr_destroy(grpc_lb_policy *pol) {
gpr_free(p);
}
void rr_shutdown(grpc_lb_policy *pol) {
void rr_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
size_t i;
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
gpr_mu_lock(&p->mu);
for (i = 0; i < p->num_subchannels; i++) {
del_interested_parties_locked(p, i);
del_interested_parties_locked(exec_ctx, p, i);
}
p->shutdown = 1;
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_iomgr_add_delayed_callback(pp->on_complete, 0);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 0);
gpr_free(pp);
}
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_FATAL_FAILURE,
"shutdown");
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "shutdown");
gpr_mu_unlock(&p->mu);
}
static void start_picking(round_robin_lb_policy *p) {
static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
size_t i;
p->started_picking = 1;
for (i = 0; i < p->num_subchannels; i++) {
p->subchannel_connectivity[i] = GRPC_CHANNEL_IDLE;
grpc_subchannel_notify_on_state_change(p->subchannels[i],
grpc_subchannel_notify_on_state_change(exec_ctx, p->subchannels[i],
&p->subchannel_connectivity[i],
&p->connectivity_changed_cbs[i]);
GRPC_LB_POLICY_REF(&p->base, "round_robin_connectivity");
}
}
void rr_exit_idle(grpc_lb_policy *pol) {
void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
gpr_mu_lock(&p->mu);
if (!p->started_picking) {
start_picking(p);
start_picking(exec_ctx, p);
}
gpr_mu_unlock(&p->mu);
}
void rr_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
grpc_iomgr_closure *on_complete) {
void rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
grpc_subchannel **target, grpc_closure *on_complete) {
size_t i;
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
@ -304,13 +303,14 @@ void rr_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
}
/* only advance the last picked pointer if the selection was used */
advance_last_picked_locked(p);
on_complete->cb(on_complete->cb_arg, 1);
on_complete->cb(exec_ctx, on_complete->cb_arg, 1);
} else {
if (!p->started_picking) {
start_picking(p);
start_picking(exec_ctx, p);
}
for (i = 0; i < p->num_subchannels; i++) {
grpc_subchannel_add_interested_party(p->subchannels[i], pollset);
grpc_subchannel_add_interested_party(exec_ctx, p->subchannels[i],
pollset);
}
pp = gpr_malloc(sizeof(*pp));
pp->next = p->pending_picks;
@ -322,7 +322,8 @@ void rr_pick(grpc_lb_policy *pol, grpc_pollset *pollset,
}
}
static void rr_connectivity_changed(void *arg, int iomgr_success) {
static void rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
connectivity_changed_cb_arg *cb_arg = arg;
round_robin_lb_policy *p = cb_arg->p;
/* index over p->subchannels of this cb's subchannel */
@ -337,16 +338,15 @@ static void rr_connectivity_changed(void *arg, int iomgr_success) {
gpr_mu_lock(&p->mu);
this_connectivity =
&p->subchannel_connectivity[this_idx];
this_connectivity = &p->subchannel_connectivity[this_idx];
if (p->shutdown) {
unref = 1;
} else {
switch (*this_connectivity) {
case GRPC_CHANNEL_READY:
grpc_connectivity_state_set(&p->state_tracker, GRPC_CHANNEL_READY,
"connecting_ready");
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_READY, "connecting_ready");
/* add the newly connected subchannel to the list of connected ones.
* Note that it goes to the "end of the line". */
p->subchannel_index_to_readylist_node[this_idx] =
@ -368,79 +368,82 @@ static void rr_connectivity_changed(void *arg, int iomgr_success) {
"[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)",
selected->subchannel, selected);
}
grpc_subchannel_del_interested_party(selected->subchannel,
grpc_subchannel_del_interested_party(exec_ctx, selected->subchannel,
pp->pollset);
grpc_iomgr_add_delayed_callback(pp->on_complete, 1);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
gpr_free(pp);
}
grpc_subchannel_notify_on_state_change(
p->subchannels[this_idx], this_connectivity,
exec_ctx, p->subchannels[this_idx], this_connectivity,
&p->connectivity_changed_cbs[this_idx]);
break;
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_IDLE:
grpc_connectivity_state_set(&p->state_tracker, *this_connectivity,
"connecting_changed");
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
*this_connectivity, "connecting_changed");
grpc_subchannel_notify_on_state_change(
p->subchannels[this_idx], this_connectivity,
exec_ctx, p->subchannels[this_idx], this_connectivity,
&p->connectivity_changed_cbs[this_idx]);
break;
case GRPC_CHANNEL_TRANSIENT_FAILURE:
del_interested_parties_locked(p, this_idx);
del_interested_parties_locked(exec_ctx, p, this_idx);
/* renew state notification */
grpc_subchannel_notify_on_state_change(
p->subchannels[this_idx], this_connectivity,
exec_ctx, p->subchannels[this_idx], this_connectivity,
&p->connectivity_changed_cbs[this_idx]);
/* remove from ready list if still present */
if (p->subchannel_index_to_readylist_node[this_idx] != NULL) {
remove_disconnected_sc_locked(p, p->subchannel_index_to_readylist_node[this_idx]);
remove_disconnected_sc_locked(
p, p->subchannel_index_to_readylist_node[this_idx]);
p->subchannel_index_to_readylist_node[this_idx] = NULL;
}
grpc_connectivity_state_set(&p->state_tracker,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
break;
case GRPC_CHANNEL_FATAL_FAILURE:
del_interested_parties_locked(p, this_idx);
del_interested_parties_locked(exec_ctx, p, this_idx);
if (p->subchannel_index_to_readylist_node[this_idx] != NULL) {
remove_disconnected_sc_locked(p, p->subchannel_index_to_readylist_node[this_idx]);
remove_disconnected_sc_locked(
p, p->subchannel_index_to_readylist_node[this_idx]);
p->subchannel_index_to_readylist_node[this_idx] = NULL;
}
GPR_SWAP(grpc_subchannel *, p->subchannels[this_idx],
p->subchannels[p->num_subchannels - 1]);
p->num_subchannels--;
GRPC_SUBCHANNEL_UNREF(p->subchannels[p->num_subchannels],
GRPC_SUBCHANNEL_UNREF(exec_ctx, p->subchannels[p->num_subchannels],
"round_robin");
if (p->num_subchannels == 0) {
grpc_connectivity_state_set(&p->state_tracker,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE,
"no_more_channels");
while ((pp = p->pending_picks)) {
p->pending_picks = pp->next;
*pp->target = NULL;
grpc_iomgr_add_delayed_callback(pp->on_complete, 1);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, 1);
gpr_free(pp);
}
unref = 1;
} else {
grpc_connectivity_state_set(&p->state_tracker,
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"subchannel_failed");
}
} /* switch */
} /* !unref */
} /* switch */
} /* !unref */
gpr_mu_unlock(&p->mu);
if (unref) {
GRPC_LB_POLICY_UNREF(&p->base, "round_robin_connectivity");
GRPC_LB_POLICY_UNREF(exec_ctx, &p->base, "round_robin_connectivity");
}
}
static void rr_broadcast(grpc_lb_policy *pol, grpc_transport_op *op) {
static void rr_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_transport_op *op) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
size_t i;
size_t n;
@ -456,13 +459,14 @@ static void rr_broadcast(grpc_lb_policy *pol, grpc_transport_op *op) {
gpr_mu_unlock(&p->mu);
for (i = 0; i < n; i++) {
grpc_subchannel_process_transport_op(subchannels[i], op);
GRPC_SUBCHANNEL_UNREF(subchannels[i], "rr_broadcast");
grpc_subchannel_process_transport_op(exec_ctx, subchannels[i], op);
GRPC_SUBCHANNEL_UNREF(exec_ctx, subchannels[i], "rr_broadcast");
}
gpr_free(subchannels);
}
static grpc_connectivity_state rr_check_connectivity(grpc_lb_policy *pol) {
static grpc_connectivity_state rr_check_connectivity(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *pol) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
grpc_connectivity_state st;
gpr_mu_lock(&p->mu);
@ -471,13 +475,14 @@ static grpc_connectivity_state rr_check_connectivity(grpc_lb_policy *pol) {
return st;
}
static void rr_notify_on_state_change(grpc_lb_policy *pol,
static void rr_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *pol,
grpc_connectivity_state *current,
grpc_iomgr_closure *notify) {
grpc_closure *notify) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
gpr_mu_lock(&p->mu);
grpc_connectivity_state_notify_on_state_change(&p->state_tracker, current,
notify);
grpc_connectivity_state_notify_on_state_change(exec_ctx, &p->state_tracker,
current, notify);
gpr_mu_unlock(&p->mu);
}
@ -490,7 +495,6 @@ static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
rr_check_connectivity,
rr_notify_on_state_change};
static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {}
@ -502,7 +506,8 @@ static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory,
GPR_ASSERT(args->num_subchannels > 0);
memset(p, 0, sizeof(*p));
grpc_lb_policy_init(&p->base, &round_robin_lb_policy_vtable);
p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
p->subchannels =
gpr_malloc(sizeof(grpc_subchannel *) * args->num_subchannels);
p->num_subchannels = args->num_subchannels;
grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE,
"round_robin");
@ -511,17 +516,17 @@ static grpc_lb_policy *create_round_robin(grpc_lb_policy_factory *factory,
gpr_mu_init(&p->mu);
p->connectivity_changed_cbs =
gpr_malloc(sizeof(grpc_iomgr_closure) * args->num_subchannels);
gpr_malloc(sizeof(grpc_closure) * args->num_subchannels);
p->subchannel_connectivity =
gpr_malloc(sizeof(grpc_connectivity_state) * args->num_subchannels);
p->cb_args =
gpr_malloc(sizeof(connectivity_changed_cb_arg) * args->num_subchannels);
for(i = 0; i < args->num_subchannels; i++) {
for (i = 0; i < args->num_subchannels; i++) {
p->cb_args[i].subchannel_idx = i;
p->cb_args[i].p = p;
grpc_iomgr_closure_init(&p->connectivity_changed_cbs[i],
rr_connectivity_changed, &p->cb_args[i]);
grpc_closure_init(&p->connectivity_changed_cbs[i], rr_connectivity_changed,
&p->cb_args[i]);
}
/* The (dummy node) root of the ready list */

@ -43,5 +43,4 @@ extern int grpc_lb_round_robin_trace;
/** Returns a load balancing factory for the round robin policy */
grpc_lb_policy_factory *grpc_round_robin_lb_factory_create();
#endif

@ -51,44 +51,48 @@ void grpc_lb_policy_ref(grpc_lb_policy *policy) {
}
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
void grpc_lb_policy_unref(grpc_lb_policy *policy, const char *file, int line,
const char *reason) {
void grpc_lb_policy_unref(grpc_lb_policy *policy,
grpc_closure_list *closure_list, const char *file,
int line, const char *reason) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "LB_POLICY:%p unref %d -> %d %s",
policy, (int)policy->refs.count, (int)policy->refs.count - 1, reason);
#else
void grpc_lb_policy_unref(grpc_lb_policy *policy) {
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
#endif
if (gpr_unref(&policy->refs)) {
policy->vtable->destroy(policy);
policy->vtable->destroy(exec_ctx, policy);
}
}
void grpc_lb_policy_shutdown(grpc_lb_policy *policy) {
policy->vtable->shutdown(policy);
void grpc_lb_policy_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
policy->vtable->shutdown(exec_ctx, policy);
}
void grpc_lb_policy_pick(grpc_lb_policy *policy, grpc_pollset *pollset,
void grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata,
grpc_subchannel **target,
grpc_iomgr_closure *on_complete) {
policy->vtable->pick(policy, pollset, initial_metadata, target, on_complete);
grpc_subchannel **target, grpc_closure *on_complete) {
policy->vtable->pick(exec_ctx, policy, pollset, initial_metadata, target,
on_complete);
}
void grpc_lb_policy_broadcast(grpc_lb_policy *policy, grpc_transport_op *op) {
policy->vtable->broadcast(policy, op);
void grpc_lb_policy_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_transport_op *op) {
policy->vtable->broadcast(exec_ctx, policy, op);
}
void grpc_lb_policy_exit_idle(grpc_lb_policy *policy) {
policy->vtable->exit_idle(policy);
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
policy->vtable->exit_idle(exec_ctx, policy);
}
void grpc_lb_policy_notify_on_state_change(grpc_lb_policy *policy,
void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,
grpc_iomgr_closure *closure) {
policy->vtable->notify_on_state_change(policy, state, closure);
grpc_closure *closure) {
policy->vtable->notify_on_state_change(exec_ctx, policy, state, closure);
}
grpc_connectivity_state grpc_lb_policy_check_connectivity(
grpc_lb_policy *policy) {
return policy->vtable->check_connectivity(policy);
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
return policy->vtable->check_connectivity(exec_ctx, policy);
}

@ -35,6 +35,7 @@
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICY_H
#include "src/core/client_config/subchannel.h"
#include "src/core/transport/connectivity_state.h"
/** A load balancing policy: specified by a vtable and a struct (which
is expected to be extended to contain some parameters) */
@ -50,45 +51,48 @@ struct grpc_lb_policy {
};
struct grpc_lb_policy_vtable {
void (*destroy)(grpc_lb_policy *policy);
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
void (*shutdown)(grpc_lb_policy *policy);
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** implement grpc_lb_policy_pick */
void (*pick)(grpc_lb_policy *policy, grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata, grpc_subchannel **target,
grpc_iomgr_closure *on_complete);
void (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
grpc_subchannel **target, grpc_closure *on_complete);
/** try to enter a READY connectivity state */
void (*exit_idle)(grpc_lb_policy *policy);
void (*exit_idle)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** broadcast a transport op to all subchannels */
void (*broadcast)(grpc_lb_policy *policy, grpc_transport_op *op);
void (*broadcast)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_transport_op *op);
/** check the current connectivity of the lb_policy */
grpc_connectivity_state (*check_connectivity)(grpc_lb_policy *policy);
grpc_connectivity_state (*check_connectivity)(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy);
/** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the policy */
void (*notify_on_state_change)(grpc_lb_policy *policy,
void (*notify_on_state_change)(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,
grpc_iomgr_closure *closure);
grpc_closure *closure);
};
#ifdef GRPC_LB_POLICY_REFCOUNT_DEBUG
#define GRPC_LB_POLICY_REF(p, r) \
grpc_lb_policy_ref((p), __FILE__, __LINE__, (r))
#define GRPC_LB_POLICY_UNREF(p, r) \
grpc_lb_policy_unref((p), __FILE__, __LINE__, (r))
#define GRPC_LB_POLICY_UNREF(exec_ctx, p, r) \
grpc_lb_policy_unref((exec_ctx), (p), __FILE__, __LINE__, (r))
void grpc_lb_policy_ref(grpc_lb_policy *policy, const char *file, int line,
const char *reason);
void grpc_lb_policy_unref(grpc_lb_policy *policy, const char *file, int line,
const char *reason);
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
const char *file, int line, const char *reason);
#else
#define GRPC_LB_POLICY_REF(p, r) grpc_lb_policy_ref((p))
#define GRPC_LB_POLICY_UNREF(p, r) grpc_lb_policy_unref((p))
#define GRPC_LB_POLICY_UNREF(cl, p, r) grpc_lb_policy_unref((cl), (p))
void grpc_lb_policy_ref(grpc_lb_policy *policy);
void grpc_lb_policy_unref(grpc_lb_policy *policy);
void grpc_lb_policy_unref(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
#endif
/** called by concrete implementations to initialize the base struct */
@ -96,26 +100,28 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
const grpc_lb_policy_vtable *vtable);
/** Start shutting down (fail any pending picks) */
void grpc_lb_policy_shutdown(grpc_lb_policy *policy);
void grpc_lb_policy_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
/** Given initial metadata in \a initial_metadata, find an appropriate
target for this rpc, and 'return' it by calling \a on_complete after setting
\a target.
Picking can be asynchronous. Any IO should be done under \a pollset. */
void grpc_lb_policy_pick(grpc_lb_policy *policy, grpc_pollset *pollset,
void grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata,
grpc_subchannel **target,
grpc_iomgr_closure *on_complete);
grpc_subchannel **target, grpc_closure *on_complete);
void grpc_lb_policy_broadcast(grpc_lb_policy *policy, grpc_transport_op *op);
void grpc_lb_policy_broadcast(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_transport_op *op);
void grpc_lb_policy_exit_idle(grpc_lb_policy *policy);
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
void grpc_lb_policy_notify_on_state_change(grpc_lb_policy *policy,
void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
grpc_connectivity_state *state,
grpc_iomgr_closure *closure);
grpc_closure *closure);
grpc_connectivity_state grpc_lb_policy_check_connectivity(
grpc_lb_policy *policy);
grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
#endif /* GRPC_INTERNAL_CORE_CONFIG_LB_POLICY_H */

@ -33,15 +33,16 @@
#include "src/core/client_config/lb_policy_factory.h"
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory *factory) {
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
factory->vtable->ref(factory);
}
void grpc_lb_policy_factory_unref(grpc_lb_policy_factory *factory) {
void grpc_lb_policy_factory_unref(grpc_lb_policy_factory* factory) {
factory->vtable->unref(factory);
}
grpc_lb_policy *grpc_lb_policy_factory_create_lb_policy(
grpc_lb_policy_factory *factory, grpc_lb_policy_args *args) {
grpc_lb_policy* grpc_lb_policy_factory_create_lb_policy(
grpc_lb_policy_factory* factory, grpc_lb_policy_args* args) {
if (factory == NULL) return NULL;
return factory->vtable->create_lb_policy(factory, args);
}

@ -65,7 +65,7 @@ void grpc_register_lb_policy(grpc_lb_policy_factory *factory) {
g_all_of_the_lb_policies[g_number_of_lb_policies++] = factory;
}
static grpc_lb_policy_factory *lookup_factory(const char* name) {
static grpc_lb_policy_factory *lookup_factory(const char *name) {
int i;
if (name == NULL) return NULL;
@ -82,7 +82,7 @@ static grpc_lb_policy_factory *lookup_factory(const char* name) {
grpc_lb_policy *grpc_lb_policy_create(const char *name,
grpc_lb_policy_args *args) {
grpc_lb_policy_factory *factory = lookup_factory(name);
grpc_lb_policy *lb_policy = grpc_lb_policy_factory_create_lb_policy(
factory, args);
grpc_lb_policy *lb_policy =
grpc_lb_policy_factory_create_lb_policy(factory, args);
return lb_policy;
}

@ -40,8 +40,8 @@ void grpc_resolver_init(grpc_resolver *resolver,
}
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
void grpc_resolver_ref(grpc_resolver *resolver, const char *file, int line,
const char *reason) {
void grpc_resolver_ref(grpc_resolver *resolver, grpc_closure_list *closure_list,
const char *file, int line, const char *reason) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p ref %d -> %d %s",
resolver, (int)resolver->refs.count, (int)resolver->refs.count + 1,
reason);
@ -52,32 +52,34 @@ void grpc_resolver_ref(grpc_resolver *resolver) {
}
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
void grpc_resolver_unref(grpc_resolver *resolver, const char *file, int line,
const char *reason) {
void grpc_resolver_unref(grpc_resolver *resolver,
grpc_closure_list *closure_list, const char *file,
int line, const char *reason) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "RESOLVER:%p unref %d -> %d %s",
resolver, (int)resolver->refs.count, (int)resolver->refs.count - 1,
reason);
#else
void grpc_resolver_unref(grpc_resolver *resolver) {
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
#endif
if (gpr_unref(&resolver->refs)) {
resolver->vtable->destroy(resolver);
resolver->vtable->destroy(exec_ctx, resolver);
}
}
void grpc_resolver_shutdown(grpc_resolver *resolver) {
resolver->vtable->shutdown(resolver);
void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
resolver->vtable->shutdown(exec_ctx, resolver);
}
void grpc_resolver_channel_saw_error(grpc_resolver *resolver,
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
struct sockaddr *failing_address,
int failing_address_len) {
resolver->vtable->channel_saw_error(resolver, failing_address,
resolver->vtable->channel_saw_error(exec_ctx, resolver, failing_address,
failing_address_len);
}
void grpc_resolver_next(grpc_resolver *resolver,
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
resolver->vtable->next(resolver, target_config, on_complete);
grpc_closure *on_complete) {
resolver->vtable->next(exec_ctx, resolver, target_config, on_complete);
}

@ -49,38 +49,39 @@ struct grpc_resolver {
};
struct grpc_resolver_vtable {
void (*destroy)(grpc_resolver *resolver);
void (*shutdown)(grpc_resolver *resolver);
void (*channel_saw_error)(grpc_resolver *resolver,
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
struct sockaddr *failing_address,
int failing_address_len);
void (*next)(grpc_resolver *resolver, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config, grpc_closure *on_complete);
};
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p), __FILE__, __LINE__, (r))
#define GRPC_RESOLVER_UNREF(p, r) \
grpc_resolver_unref((p), __FILE__, __LINE__, (r))
#define GRPC_RESOLVER_UNREF(cl, p, r) \
grpc_resolver_unref((cl), (p), __FILE__, __LINE__, (r))
void grpc_resolver_ref(grpc_resolver *policy, const char *file, int line,
const char *reason);
void grpc_resolver_unref(grpc_resolver *policy, const char *file, int line,
const char *reason);
void grpc_resolver_unref(grpc_resolver *policy, grpc_closure_list *closure_list,
const char *file, int line, const char *reason);
#else
#define GRPC_RESOLVER_REF(p, r) grpc_resolver_ref((p))
#define GRPC_RESOLVER_UNREF(p, r) grpc_resolver_unref((p))
#define GRPC_RESOLVER_UNREF(cl, p, r) grpc_resolver_unref((cl), (p))
void grpc_resolver_ref(grpc_resolver *policy);
void grpc_resolver_unref(grpc_resolver *policy);
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
#endif
void grpc_resolver_init(grpc_resolver *resolver,
const grpc_resolver_vtable *vtable);
void grpc_resolver_shutdown(grpc_resolver *resolver);
void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
/** Notification that the channel has seen an error on some address.
Can be used as a hint that re-resolution is desirable soon. */
void grpc_resolver_channel_saw_error(grpc_resolver *resolver,
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
struct sockaddr *failing_address,
int failing_address_len);
@ -90,8 +91,8 @@ void grpc_resolver_channel_saw_error(grpc_resolver *resolver,
If resolution is fatally broken, set *target_config to NULL and
schedule on_complete. */
void grpc_resolver_next(grpc_resolver *resolver,
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
grpc_closure *on_complete);
#endif /* GRPC_INTERNAL_CORE_CONFIG_RESOLVER_H */

@ -33,24 +33,23 @@
#include "src/core/client_config/resolver_factory.h"
void grpc_resolver_factory_ref(grpc_resolver_factory *factory) {
void grpc_resolver_factory_ref(grpc_resolver_factory* factory) {
factory->vtable->ref(factory);
}
void grpc_resolver_factory_unref(grpc_resolver_factory *factory) {
void grpc_resolver_factory_unref(grpc_resolver_factory* factory) {
factory->vtable->unref(factory);
}
/** Create a resolver instance for a name */
grpc_resolver *grpc_resolver_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory) {
grpc_resolver* grpc_resolver_factory_create_resolver(
grpc_resolver_factory* factory, grpc_resolver_args* args) {
if (factory == NULL) return NULL;
return factory->vtable->create_resolver(factory, uri, subchannel_factory);
return factory->vtable->create_resolver(factory, args);
}
char *grpc_resolver_factory_get_default_authority(
grpc_resolver_factory *factory, grpc_uri *uri) {
char* grpc_resolver_factory_get_default_authority(
grpc_resolver_factory* factory, grpc_uri* uri) {
if (factory == NULL) return NULL;
return factory->vtable->get_default_authority(factory, uri);
}

@ -47,14 +47,18 @@ struct grpc_resolver_factory {
const grpc_resolver_factory_vtable *vtable;
};
typedef struct grpc_resolver_args {
grpc_uri *uri;
grpc_subchannel_factory *subchannel_factory;
} grpc_resolver_args;
struct grpc_resolver_factory_vtable {
void (*ref)(grpc_resolver_factory *factory);
void (*unref)(grpc_resolver_factory *factory);
/** Implementation of grpc_resolver_factory_create_resolver */
grpc_resolver *(*create_resolver)(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory);
grpc_resolver *(*create_resolver)(grpc_resolver_factory *factory,
grpc_resolver_args *args);
/** Implementation of grpc_resolver_factory_get_default_authority */
char *(*get_default_authority)(grpc_resolver_factory *factory, grpc_uri *uri);
@ -68,8 +72,7 @@ void grpc_resolver_factory_unref(grpc_resolver_factory *resolver);
/** Create a resolver instance for a name */
grpc_resolver *grpc_resolver_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory);
grpc_resolver_factory *factory, grpc_resolver_args *args);
/** Return a (freshly allocated with gpr_malloc) string representing
the default authority to use for this scheme. */

@ -118,8 +118,12 @@ grpc_resolver *grpc_resolver_create(
const char *target, grpc_subchannel_factory *subchannel_factory) {
grpc_uri *uri = NULL;
grpc_resolver_factory *factory = resolve_factory(target, &uri);
grpc_resolver *resolver =
grpc_resolver_factory_create_resolver(factory, uri, subchannel_factory);
grpc_resolver *resolver;
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
args.uri = uri;
args.subchannel_factory = subchannel_factory;
resolver = grpc_resolver_factory_create_resolver(factory, &args);
grpc_uri_destroy(uri);
return resolver;
}

@ -67,40 +67,43 @@ typedef struct {
/** which version of resolved_config is current? */
int resolved_version;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
grpc_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
/** current (fully resolved) config */
grpc_client_config *resolved_config;
} dns_resolver;
static void dns_destroy(grpc_resolver *r);
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_start_resolving_locked(dns_resolver *r);
static void dns_maybe_finish_next_locked(dns_resolver *r);
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r);
static void dns_shutdown(grpc_resolver *r);
static void dns_channel_saw_error(grpc_resolver *r,
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void dns_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_client_config **target_config,
grpc_closure *on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = {
dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next};
static void dns_shutdown(grpc_resolver *resolver) {
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
grpc_iomgr_add_callback(r->next_completion);
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
}
static void dns_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver, struct sockaddr *sa,
int len) {
dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
@ -110,9 +113,9 @@ static void dns_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
gpr_mu_unlock(&r->mu);
}
static void dns_next(grpc_resolver *resolver,
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
grpc_closure *on_complete) {
dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
@ -121,12 +124,13 @@ static void dns_next(grpc_resolver *resolver,
if (r->resolved_version == 0 && !r->resolving) {
dns_start_resolving_locked(r);
} else {
dns_maybe_finish_next_locked(r);
dns_maybe_finish_next_locked(exec_ctx, r);
}
gpr_mu_unlock(&r->mu);
}
static void dns_on_resolved(void *arg, grpc_resolved_addresses *addresses) {
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
dns_resolver *r = arg;
grpc_client_config *config = NULL;
grpc_subchannel **subchannels;
@ -142,13 +146,14 @@ static void dns_on_resolved(void *arg, grpc_resolved_addresses *addresses) {
args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
args.addr_len = (size_t)addresses->addrs[i].len;
subchannels[i] = grpc_subchannel_factory_create_subchannel(
r->subchannel_factory, &args);
exec_ctx, r->subchannel_factory, &args);
}
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.subchannels = subchannels;
lb_policy_args.num_subchannels = addresses->naddrs;
lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "construction");
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
grpc_resolved_addresses_destroy(addresses);
gpr_free(subchannels);
}
@ -156,14 +161,14 @@ static void dns_on_resolved(void *arg, grpc_resolved_addresses *addresses) {
GPR_ASSERT(r->resolving);
r->resolving = 0;
if (r->resolved_config) {
grpc_client_config_unref(r->resolved_config);
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
r->resolved_config = config;
r->resolved_version++;
dns_maybe_finish_next_locked(r);
dns_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(&r->base, "dns-resolving");
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
}
static void dns_start_resolving_locked(dns_resolver *r) {
@ -173,41 +178,41 @@ static void dns_start_resolving_locked(dns_resolver *r) {
grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
}
static void dns_maybe_finish_next_locked(dns_resolver *r) {
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r) {
if (r->next_completion != NULL &&
r->resolved_version != r->published_version) {
*r->target_config = r->resolved_config;
if (r->resolved_config) {
grpc_client_config_ref(r->resolved_config);
}
grpc_iomgr_add_callback(r->next_completion);
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
r->next_completion = NULL;
r->published_version = r->resolved_version;
}
}
static void dns_destroy(grpc_resolver *gr) {
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
dns_resolver *r = (dns_resolver *)gr;
gpr_mu_destroy(&r->mu);
if (r->resolved_config) {
grpc_client_config_unref(r->resolved_config);
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
grpc_subchannel_factory_unref(r->subchannel_factory);
grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
gpr_free(r->name);
gpr_free(r->default_port);
gpr_free(r->lb_policy_name);
gpr_free(r);
}
static grpc_resolver *dns_create(
grpc_uri *uri, const char *default_port,
const char* lb_policy_name,
grpc_subchannel_factory *subchannel_factory) {
static grpc_resolver *dns_create(grpc_resolver_args *args,
const char *default_port,
const char *lb_policy_name) {
dns_resolver *r;
const char *path = uri->path;
const char *path = args->uri->path;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
if (0 != strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based dns uri's not supported");
return NULL;
}
@ -220,8 +225,8 @@ static grpc_resolver *dns_create(
grpc_resolver_init(&r->base, &dns_resolver_vtable);
r->name = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->subchannel_factory = subchannel_factory;
grpc_subchannel_factory_ref(subchannel_factory);
r->subchannel_factory = args->subchannel_factory;
grpc_subchannel_factory_ref(r->subchannel_factory);
r->lb_policy_name = gpr_strdup(lb_policy_name);
return &r->base;
}
@ -235,9 +240,8 @@ static void dns_factory_ref(grpc_resolver_factory *factory) {}
static void dns_factory_unref(grpc_resolver_factory *factory) {}
static grpc_resolver *dns_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory) {
return dns_create(uri, "https", "pick_first", subchannel_factory);
grpc_resolver_factory *factory, grpc_resolver_args *args) {
return dns_create(args, "https", "pick_first");
}
char *dns_factory_get_default_host_name(grpc_resolver_factory *factory,

@ -71,54 +71,59 @@ typedef struct {
/** have we published? */
int published;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
grpc_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
} sockaddr_resolver;
static void sockaddr_destroy(grpc_resolver *r);
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r);
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r);
static void sockaddr_shutdown(grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_resolver *r,
static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void sockaddr_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_client_config **target_config,
grpc_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = {
sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error,
sockaddr_next};
static void sockaddr_shutdown(grpc_resolver *resolver) {
static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
/* TODO(ctiller): add delayed callback */
grpc_iomgr_add_callback(r->next_completion);
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
r->next_completion = NULL;
}
gpr_mu_unlock(&r->mu);
}
static void sockaddr_channel_saw_error(grpc_resolver *resolver,
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
struct sockaddr *sa, int len) {}
static void sockaddr_next(grpc_resolver *resolver,
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
grpc_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete;
r->target_config = target_config;
sockaddr_maybe_finish_next_locked(r);
sockaddr_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
}
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r) {
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r) {
grpc_client_config *cfg;
grpc_lb_policy *lb_policy;
grpc_lb_policy_args lb_policy_args;
@ -134,26 +139,26 @@ static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r) {
args.addr = (struct sockaddr *)&r->addrs[i];
args.addr_len = r->addrs_len[i];
subchannels[i] = grpc_subchannel_factory_create_subchannel(
r->subchannel_factory, &args);
exec_ctx, r->subchannel_factory, &args);
}
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.subchannels = subchannels;
lb_policy_args.num_subchannels = r->num_addrs;
lb_policy =
grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
gpr_free(subchannels);
grpc_client_config_set_lb_policy(cfg, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "unix");
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
r->published = 1;
*r->target_config = cfg;
grpc_iomgr_add_callback(r->next_completion);
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
r->next_completion = NULL;
}
}
static void sockaddr_destroy(grpc_resolver *gr) {
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
gpr_free(r->addrs);
gpr_free(r->addrs_len);
gpr_free(r->lb_policy_name);
@ -277,9 +282,9 @@ done:
}
static void do_nothing(void *ignored) {}
static grpc_resolver *sockaddr_create(
grpc_uri *uri, const char *default_lb_policy_name,
grpc_subchannel_factory *subchannel_factory,
grpc_resolver_args *args, const char *default_lb_policy_name,
int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) {
size_t i;
int errors_found = 0; /* GPR_FALSE */
@ -287,8 +292,9 @@ static grpc_resolver *sockaddr_create(
gpr_slice path_slice;
gpr_slice_buffer path_parts;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
if (0 != strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme",
args->uri->scheme);
return NULL;
}
@ -296,11 +302,12 @@ static grpc_resolver *sockaddr_create(
memset(r, 0, sizeof(*r));
r->lb_policy_name = NULL;
if (0 != strcmp(uri->query, "")) {
if (0 != strcmp(args->uri->query, "")) {
gpr_slice query_slice;
gpr_slice_buffer query_parts;
query_slice = gpr_slice_new(uri->query, strlen(uri->query), do_nothing);
query_slice =
gpr_slice_new(args->uri->query, strlen(args->uri->query), do_nothing);
gpr_slice_buffer_init(&query_parts);
gpr_slice_split(query_slice, "=", &query_parts);
GPR_ASSERT(query_parts.count == 2);
@ -314,7 +321,8 @@ static grpc_resolver *sockaddr_create(
r->lb_policy_name = gpr_strdup(default_lb_policy_name);
}
path_slice = gpr_slice_new(uri->path, strlen(uri->path), do_nothing);
path_slice =
gpr_slice_new(args->uri->path, strlen(args->uri->path), do_nothing);
gpr_slice_buffer_init(&path_parts);
gpr_slice_split(path_slice, ",", &path_parts);
@ -322,9 +330,9 @@ static grpc_resolver *sockaddr_create(
r->addrs = gpr_malloc(sizeof(struct sockaddr_storage) * r->num_addrs);
r->addrs_len = gpr_malloc(sizeof(*r->addrs_len) * r->num_addrs);
for(i = 0; i < r->num_addrs; i++) {
grpc_uri ith_uri = *uri;
char* part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
for (i = 0; i < r->num_addrs; i++) {
grpc_uri ith_uri = *args->uri;
char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
ith_uri.path = part_str;
if (!parse(&ith_uri, &r->addrs[i], &r->addrs_len[i])) {
errors_found = 1; /* GPR_TRUE */
@ -343,9 +351,9 @@ static grpc_resolver *sockaddr_create(
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
r->subchannel_factory = subchannel_factory;
r->subchannel_factory = args->subchannel_factory;
grpc_subchannel_factory_ref(r->subchannel_factory);
grpc_subchannel_factory_ref(subchannel_factory);
return &r->base;
}
@ -359,10 +367,8 @@ static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
#define DECL_FACTORY(name) \
static grpc_resolver *name##_factory_create_resolver( \
grpc_resolver_factory *factory, grpc_uri *uri, \
grpc_subchannel_factory *subchannel_factory) { \
return sockaddr_create(uri, "pick_first", \
subchannel_factory, parse_##name); \
grpc_resolver_factory *factory, grpc_resolver_args *args) { \
return sockaddr_create(args, "pick_first", parse_##name); \
} \
static const grpc_resolver_factory_vtable name##_factory_vtable = { \
sockaddr_factory_ref, sockaddr_factory_unref, \
@ -376,5 +382,4 @@ static void sockaddr_factory_unref(grpc_resolver_factory *factory) {}
#ifdef GPR_POSIX_SOCKET
DECL_FACTORY(unix)
#endif
DECL_FACTORY(ipv4)
DECL_FACTORY(ipv6)
DECL_FACTORY(ipv4) DECL_FACTORY(ipv6)

@ -71,7 +71,7 @@ typedef struct {
/** which version of resolved_config is current? */
int resolved_version;
/** pending next completion, or NULL */
grpc_iomgr_closure *next_completion;
grpc_closure *next_completion;
/** target config address for next completion */
grpc_client_config **target_config;
/** current (fully resolved) config */
@ -87,35 +87,44 @@ typedef struct {
int resolved_num;
} zookeeper_resolver;
static void zookeeper_destroy(grpc_resolver *r);
static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void zookeeper_start_resolving_locked(zookeeper_resolver *r);
static void zookeeper_maybe_finish_next_locked(zookeeper_resolver *r);
static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
zookeeper_resolver *r);
static void zookeeper_shutdown(grpc_resolver *r);
static void zookeeper_channel_saw_error(grpc_resolver *r,
static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *r,
struct sockaddr *failing_address,
int failing_address_len);
static void zookeeper_next(grpc_resolver *r, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_client_config **target_config,
grpc_closure *on_complete);
static const grpc_resolver_vtable zookeeper_resolver_vtable = {
zookeeper_destroy, zookeeper_shutdown, zookeeper_channel_saw_error,
zookeeper_next};
static void zookeeper_shutdown(grpc_resolver *resolver) {
static void zookeeper_shutdown(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
grpc_closure *call = NULL;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) {
*r->target_config = NULL;
grpc_iomgr_add_callback(r->next_completion);
call = r->next_completion;
r->next_completion = NULL;
}
zookeeper_close(r->zookeeper_handle);
gpr_mu_unlock(&r->mu);
if (call != NULL) {
call->cb(exec_ctx, call->cb_arg, 1);
}
}
static void zookeeper_channel_saw_error(grpc_resolver *resolver,
static void zookeeper_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
struct sockaddr *sa, int len) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
@ -125,9 +134,9 @@ static void zookeeper_channel_saw_error(grpc_resolver *resolver,
gpr_mu_unlock(&r->mu);
}
static void zookeeper_next(grpc_resolver *resolver,
static void zookeeper_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_client_config **target_config,
grpc_iomgr_closure *on_complete) {
grpc_closure *on_complete) {
zookeeper_resolver *r = (zookeeper_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->next_completion == NULL);
@ -136,7 +145,7 @@ static void zookeeper_next(grpc_resolver *resolver,
if (r->resolved_version == 0 && r->resolving == 0) {
zookeeper_start_resolving_locked(r);
} else {
zookeeper_maybe_finish_next_locked(r);
zookeeper_maybe_finish_next_locked(exec_ctx, r);
}
gpr_mu_unlock(&r->mu);
}
@ -173,7 +182,7 @@ static void zookeeper_watcher(zhandle_t *zookeeper_handle, int type, int state,
/** Callback function after getting all resolved addresses
Creates a subchannel for each address */
static void zookeeper_on_resolved(void *arg,
static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
zookeeper_resolver *r = arg;
grpc_client_config *config = NULL;
@ -190,14 +199,13 @@ static void zookeeper_on_resolved(void *arg,
args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
args.addr_len = addresses->addrs[i].len;
subchannels[i] = grpc_subchannel_factory_create_subchannel(
r->subchannel_factory, &args);
exec_ctx, r->subchannel_factory, &args);
}
lb_policy_args.subchannels = subchannels;
lb_policy_args.num_subchannels = addresses->naddrs;
lb_policy =
grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "construction");
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
grpc_resolved_addresses_destroy(addresses);
gpr_free(subchannels);
}
@ -205,18 +213,18 @@ static void zookeeper_on_resolved(void *arg,
GPR_ASSERT(r->resolving == 1);
r->resolving = 0;
if (r->resolved_config != NULL) {
grpc_client_config_unref(r->resolved_config);
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
r->resolved_config = config;
r->resolved_version++;
zookeeper_maybe_finish_next_locked(r);
zookeeper_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(&r->base, "zookeeper-resolving");
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "zookeeper-resolving");
}
/** Callback function for each DNS resolved address */
static void zookeeper_dns_resolved(void *arg,
static void zookeeper_dns_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
size_t i;
zookeeper_resolver *r = arg;
@ -242,7 +250,7 @@ static void zookeeper_dns_resolved(void *arg,
resolve_done = (r->resolved_num == r->resolved_total);
gpr_mu_unlock(&r->mu);
if (resolve_done) {
zookeeper_on_resolved(r, r->resolved_addrs);
zookeeper_on_resolved(exec_ctx, r, r->resolved_addrs);
}
}
@ -291,9 +299,11 @@ static void zookeeper_get_children_node_completion(int rc, const char *value,
char *address = NULL;
zookeeper_resolver *r = (zookeeper_resolver *)arg;
int resolve_done = 0;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
if (rc != 0) {
gpr_log(GPR_ERROR, "Error in getting a child node of %s", r->name);
grpc_exec_ctx_finish(&exec_ctx);
return;
}
@ -309,9 +319,11 @@ static void zookeeper_get_children_node_completion(int rc, const char *value,
resolve_done = (r->resolved_num == r->resolved_total);
gpr_mu_unlock(&r->mu);
if (resolve_done) {
zookeeper_on_resolved(r, r->resolved_addrs);
zookeeper_on_resolved(&exec_ctx, r, r->resolved_addrs);
}
}
grpc_exec_ctx_finish(&exec_ctx);
}
static void zookeeper_get_children_completion(
@ -402,39 +414,39 @@ static void zookeeper_start_resolving_locked(zookeeper_resolver *r) {
zookeeper_resolve_address(r);
}
static void zookeeper_maybe_finish_next_locked(zookeeper_resolver *r) {
static void zookeeper_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
zookeeper_resolver *r) {
if (r->next_completion != NULL &&
r->resolved_version != r->published_version) {
*r->target_config = r->resolved_config;
if (r->resolved_config != NULL) {
grpc_client_config_ref(r->resolved_config);
}
grpc_iomgr_add_callback(r->next_completion);
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, 1);
r->next_completion = NULL;
r->published_version = r->resolved_version;
}
}
static void zookeeper_destroy(grpc_resolver *gr) {
static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
zookeeper_resolver *r = (zookeeper_resolver *)gr;
gpr_mu_destroy(&r->mu);
if (r->resolved_config != NULL) {
grpc_client_config_unref(r->resolved_config);
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
grpc_subchannel_factory_unref(r->subchannel_factory);
grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
gpr_free(r->name);
gpr_free(r->lb_policy_name);
gpr_free(r);
}
static grpc_resolver *zookeeper_create(
grpc_uri *uri, const char *lb_policy_name,
grpc_subchannel_factory *subchannel_factory) {
static grpc_resolver *zookeeper_create(grpc_resolver_args *args,
const char *lb_policy_name) {
zookeeper_resolver *r;
size_t length;
char *path = uri->path;
char *path = args->uri->path;
if (0 == strcmp(uri->authority, "")) {
if (0 == strcmp(args->uri->authority, "")) {
gpr_log(GPR_ERROR, "No authority specified in zookeeper uri");
return NULL;
}
@ -452,14 +464,16 @@ static grpc_resolver *zookeeper_create(
grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
r->name = gpr_strdup(path);
r->subchannel_factory = subchannel_factory;
r->subchannel_factory = args->subchannel_factory;
grpc_subchannel_factory_ref(r->subchannel_factory);
r->lb_policy_name = gpr_strdup(lb_policy_name);
grpc_subchannel_factory_ref(subchannel_factory);
/** Initializes zookeeper client */
zoo_set_debug_level(ZOO_LOG_LEVEL_WARN);
r->zookeeper_handle = zookeeper_init(uri->authority, zookeeper_global_watcher,
GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
r->zookeeper_handle =
zookeeper_init(args->uri->authority, zookeeper_global_watcher,
GRPC_ZOOKEEPER_SESSION_TIMEOUT, 0, 0, 0);
if (r->zookeeper_handle == NULL) {
gpr_log(GPR_ERROR, "Unable to connect to zookeeper server");
return NULL;
@ -490,15 +504,15 @@ static char *zookeeper_factory_get_default_hostname(
}
static grpc_resolver *zookeeper_factory_create_resolver(
grpc_resolver_factory *factory, grpc_uri *uri,
grpc_subchannel_factory *subchannel_factory) {
return zookeeper_create(uri, "pick_first", subchannel_factory);
grpc_resolver_factory *factory, grpc_resolver_args *args) {
return zookeeper_create(args, "pick_first");
}
static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
zookeeper_factory_ref, zookeeper_factory_unref,
zookeeper_factory_create_resolver, zookeeper_factory_get_default_hostname,
"zookeeper"};
static grpc_resolver_factory zookeeper_resolver_factory = {
&zookeeper_factory_vtable};

@ -59,7 +59,7 @@ typedef struct {
} connection;
typedef struct {
grpc_iomgr_closure closure;
grpc_closure closure;
size_t version;
grpc_subchannel *subchannel;
grpc_connectivity_state connectivity_state;
@ -67,11 +67,11 @@ typedef struct {
typedef struct waiting_for_connect {
struct waiting_for_connect *next;
grpc_iomgr_closure *notify;
grpc_closure *notify;
grpc_pollset *pollset;
grpc_subchannel_call **target;
grpc_subchannel *subchannel;
grpc_iomgr_closure continuation;
grpc_closure continuation;
} waiting_for_connect;
struct grpc_subchannel {
@ -99,7 +99,7 @@ struct grpc_subchannel {
grpc_connect_out_args connecting_result;
/** callback for connection finishing */
grpc_iomgr_closure connected;
grpc_closure connected;
/** pollset_set tracking who's interested in a connection
being setup - owned by the master channel (in particular the
@ -143,12 +143,15 @@ struct grpc_subchannel_call {
#define SUBCHANNEL_CALL_TO_CALL_STACK(call) ((grpc_call_stack *)((call) + 1))
#define CHANNEL_STACK_FROM_CONNECTION(con) ((grpc_channel_stack *)((con) + 1))
static grpc_subchannel_call *create_call(connection *con);
static void connectivity_state_changed_locked(grpc_subchannel *c,
static grpc_subchannel_call *create_call(grpc_exec_ctx *exec_ctx,
connection *con);
static void connectivity_state_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c,
const char *reason);
static grpc_connectivity_state compute_connectivity_locked(grpc_subchannel *c);
static gpr_timespec compute_connect_deadline(grpc_subchannel *c);
static void subchannel_connected(void *subchannel, int iomgr_success);
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
int iomgr_success);
static void subchannel_ref_locked(
grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
@ -156,8 +159,9 @@ static int subchannel_unref_locked(
grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) GRPC_MUST_USE_RESULT;
static void connection_ref_locked(connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
static grpc_subchannel *connection_unref_locked(
grpc_exec_ctx *exec_ctx,
connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) GRPC_MUST_USE_RESULT;
static void subchannel_destroy(grpc_subchannel *c);
static void subchannel_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel *c);
#ifdef GRPC_SUBCHANNEL_REFCOUNT_DEBUG
#define SUBCHANNEL_REF_LOCKED(p, r) \
@ -166,8 +170,8 @@ static void subchannel_destroy(grpc_subchannel *c);
subchannel_unref_locked((p), __FILE__, __LINE__, (r))
#define CONNECTION_REF_LOCKED(p, r) \
connection_ref_locked((p), __FILE__, __LINE__, (r))
#define CONNECTION_UNREF_LOCKED(p, r) \
connection_unref_locked((p), __FILE__, __LINE__, (r))
#define CONNECTION_UNREF_LOCKED(cl, p, r) \
connection_unref_locked((cl), (p), __FILE__, __LINE__, (r))
#define REF_PASS_ARGS , file, line, reason
#define REF_LOG(name, p) \
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "%s: %p ref %d -> %d %s", \
@ -179,7 +183,7 @@ static void subchannel_destroy(grpc_subchannel *c);
#define SUBCHANNEL_REF_LOCKED(p, r) subchannel_ref_locked((p))
#define SUBCHANNEL_UNREF_LOCKED(p, r) subchannel_unref_locked((p))
#define CONNECTION_REF_LOCKED(p, r) connection_ref_locked((p))
#define CONNECTION_UNREF_LOCKED(p, r) connection_unref_locked((p))
#define CONNECTION_UNREF_LOCKED(cl, p, r) connection_unref_locked((cl), (p))
#define REF_PASS_ARGS
#define REF_LOG(name, p) \
do { \
@ -193,9 +197,9 @@ static void subchannel_destroy(grpc_subchannel *c);
* connection implementation
*/
static void connection_destroy(connection *c) {
static void connection_destroy(grpc_exec_ctx *exec_ctx, connection *c) {
GPR_ASSERT(c->refs == 0);
grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CONNECTION(c));
grpc_channel_stack_destroy(exec_ctx, CHANNEL_STACK_FROM_CONNECTION(c));
gpr_free(c);
}
@ -207,14 +211,14 @@ static void connection_ref_locked(
}
static grpc_subchannel *connection_unref_locked(
connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
grpc_exec_ctx *exec_ctx, connection *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
grpc_subchannel *destroy = NULL;
UNREF_LOG("CONNECTION", c);
if (subchannel_unref_locked(c->subchannel REF_PASS_ARGS)) {
destroy = c->subchannel;
}
if (--c->refs == 0 && c->subchannel->active != c) {
connection_destroy(c);
connection_destroy(exec_ctx, c);
}
return destroy;
}
@ -241,35 +245,38 @@ void grpc_subchannel_ref(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
gpr_mu_unlock(&c->mu);
}
void grpc_subchannel_unref(grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
int destroy;
gpr_mu_lock(&c->mu);
destroy = subchannel_unref_locked(c REF_PASS_ARGS);
gpr_mu_unlock(&c->mu);
if (destroy) subchannel_destroy(c);
if (destroy) subchannel_destroy(exec_ctx, c);
}
static void subchannel_destroy(grpc_subchannel *c) {
static void subchannel_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
if (c->active != NULL) {
connection_destroy(c->active);
connection_destroy(exec_ctx, c->active);
}
gpr_free(c->filters);
gpr_free((void *)c->filters);
grpc_channel_args_destroy(c->args);
gpr_free(c->addr);
grpc_mdctx_unref(c->mdctx);
grpc_connectivity_state_destroy(&c->state_tracker);
grpc_connector_unref(c->connector);
grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
grpc_connector_unref(exec_ctx, c->connector);
gpr_free(c);
}
void grpc_subchannel_add_interested_party(grpc_subchannel *c,
void grpc_subchannel_add_interested_party(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c,
grpc_pollset *pollset) {
grpc_pollset_set_add_pollset(c->pollset_set, pollset);
grpc_pollset_set_add_pollset(exec_ctx, c->pollset_set, pollset);
}
void grpc_subchannel_del_interested_party(grpc_subchannel *c,
void grpc_subchannel_del_interested_party(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c,
grpc_pollset *pollset) {
grpc_pollset_set_del_pollset(c->pollset_set, pollset);
grpc_pollset_set_del_pollset(exec_ctx, c->pollset_set, pollset);
}
static gpr_uint32 random_seed() {
@ -287,7 +294,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
grpc_connector_ref(c->connector);
c->num_filters = args->filter_count;
c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * c->num_filters);
memcpy(c->filters, args->filters,
memcpy((void *)c->filters, args->filters,
sizeof(grpc_channel_filter *) * c->num_filters);
c->addr = gpr_malloc(args->addr_len);
memcpy(c->addr, args->addr, args->addr_len);
@ -298,14 +305,14 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
c->pollset_set = grpc_client_channel_get_connecting_pollset_set(parent_elem);
c->random = random_seed();
grpc_mdctx_ref(c->mdctx);
grpc_iomgr_closure_init(&c->connected, subchannel_connected, c);
grpc_closure_init(&c->connected, subchannel_connected, c);
grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
"subchannel");
gpr_mu_init(&c->mu);
return c;
}
static void continue_connect(grpc_subchannel *c) {
static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
grpc_connect_in_args args;
args.interested_parties = c->pollset_set;
@ -313,32 +320,33 @@ static void continue_connect(grpc_subchannel *c) {
args.addr_len = c->addr_len;
args.deadline = compute_connect_deadline(c);
args.channel_args = c->args;
args.metadata_context = c->mdctx;
grpc_connector_connect(c->connector, &args, &c->connecting_result,
grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
&c->connected);
}
static void start_connect(grpc_subchannel *c) {
static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
c->backoff_delta = gpr_time_from_seconds(
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS, GPR_TIMESPAN);
c->next_attempt =
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), c->backoff_delta);
continue_connect(c);
continue_connect(exec_ctx, c);
}
static void continue_creating_call(void *arg, int iomgr_success) {
static void continue_creating_call(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
waiting_for_connect *w4c = arg;
grpc_subchannel_del_interested_party(w4c->subchannel, w4c->pollset);
grpc_subchannel_create_call(w4c->subchannel, w4c->pollset, w4c->target,
w4c->notify);
GRPC_SUBCHANNEL_UNREF(w4c->subchannel, "waiting_for_connect");
grpc_subchannel_del_interested_party(exec_ctx, w4c->subchannel, w4c->pollset);
grpc_subchannel_create_call(exec_ctx, w4c->subchannel, w4c->pollset,
w4c->target, w4c->notify);
GRPC_SUBCHANNEL_UNREF(exec_ctx, w4c->subchannel, "waiting_for_connect");
gpr_free(w4c);
}
void grpc_subchannel_create_call(grpc_subchannel *c, grpc_pollset *pollset,
void grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
grpc_pollset *pollset,
grpc_subchannel_call **target,
grpc_iomgr_closure *notify) {
grpc_closure *notify) {
connection *con;
gpr_mu_lock(&c->mu);
if (c->active != NULL) {
@ -346,8 +354,8 @@ void grpc_subchannel_create_call(grpc_subchannel *c, grpc_pollset *pollset,
CONNECTION_REF_LOCKED(con, "call");
gpr_mu_unlock(&c->mu);
*target = create_call(con);
notify->cb(notify->cb_arg, 1);
*target = create_call(exec_ctx, con);
notify->cb(exec_ctx, notify->cb_arg, 1);
} else {
waiting_for_connect *w4c = gpr_malloc(sizeof(*w4c));
w4c->next = c->waiting;
@ -357,18 +365,18 @@ void grpc_subchannel_create_call(grpc_subchannel *c, grpc_pollset *pollset,
w4c->subchannel = c;
/* released when clearing w4c */
SUBCHANNEL_REF_LOCKED(c, "waiting_for_connect");
grpc_iomgr_closure_init(&w4c->continuation, continue_creating_call, w4c);
grpc_closure_init(&w4c->continuation, continue_creating_call, w4c);
c->waiting = w4c;
grpc_subchannel_add_interested_party(c, pollset);
grpc_subchannel_add_interested_party(exec_ctx, c, pollset);
if (!c->connecting) {
c->connecting = 1;
connectivity_state_changed_locked(c, "create_call");
connectivity_state_changed_locked(exec_ctx, c, "create_call");
/* released by connection */
SUBCHANNEL_REF_LOCKED(c, "connecting");
GRPC_CHANNEL_INTERNAL_REF(c->master, "connecting");
gpr_mu_unlock(&c->mu);
start_connect(c);
start_connect(exec_ctx, c);
} else {
gpr_mu_unlock(&c->mu);
}
@ -383,69 +391,73 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c) {
return state;
}
void grpc_subchannel_notify_on_state_change(grpc_subchannel *c,
void grpc_subchannel_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c,
grpc_connectivity_state *state,
grpc_iomgr_closure *notify) {
grpc_closure *notify) {
int do_connect = 0;
gpr_mu_lock(&c->mu);
if (grpc_connectivity_state_notify_on_state_change(&c->state_tracker, state,
notify)) {
if (grpc_connectivity_state_notify_on_state_change(
exec_ctx, &c->state_tracker, state, notify)) {
do_connect = 1;
c->connecting = 1;
/* released by connection */
SUBCHANNEL_REF_LOCKED(c, "connecting");
GRPC_CHANNEL_INTERNAL_REF(c->master, "connecting");
connectivity_state_changed_locked(c, "state_change");
connectivity_state_changed_locked(exec_ctx, c, "state_change");
}
gpr_mu_unlock(&c->mu);
if (do_connect) {
start_connect(c);
start_connect(exec_ctx, c);
}
}
void grpc_subchannel_process_transport_op(grpc_subchannel *c,
void grpc_subchannel_process_transport_op(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c,
grpc_transport_op *op) {
connection *con = NULL;
grpc_subchannel *destroy;
int cancel_alarm = 0;
gpr_mu_lock(&c->mu);
if (c->active != NULL) {
con = c->active;
CONNECTION_REF_LOCKED(con, "transport-op");
}
if (op->disconnect) {
c->disconnected = 1;
connectivity_state_changed_locked(c, "disconnect");
connectivity_state_changed_locked(exec_ctx, c, "disconnect");
if (c->have_alarm) {
cancel_alarm = 1;
}
}
if (c->active != NULL) {
con = c->active;
CONNECTION_REF_LOCKED(con, "transport-op");
}
gpr_mu_unlock(&c->mu);
if (con != NULL) {
grpc_channel_stack *channel_stack = CHANNEL_STACK_FROM_CONNECTION(con);
grpc_channel_element *top_elem =
grpc_channel_stack_element(channel_stack, 0);
top_elem->filter->start_transport_op(top_elem, op);
top_elem->filter->start_transport_op(exec_ctx, top_elem, op);
gpr_mu_lock(&c->mu);
destroy = CONNECTION_UNREF_LOCKED(con, "transport-op");
destroy = CONNECTION_UNREF_LOCKED(exec_ctx, con, "transport-op");
gpr_mu_unlock(&c->mu);
if (destroy) {
subchannel_destroy(destroy);
subchannel_destroy(exec_ctx, destroy);
}
}
if (cancel_alarm) {
grpc_alarm_cancel(&c->alarm);
grpc_alarm_cancel(exec_ctx, &c->alarm);
}
if (op->disconnect) {
grpc_connector_shutdown(c->connector);
grpc_connector_shutdown(exec_ctx, c->connector);
}
}
static void on_state_changed(void *p, int iomgr_success) {
static void on_state_changed(grpc_exec_ctx *exec_ctx, void *p,
int iomgr_success) {
state_watcher *sw = p;
grpc_subchannel *c = sw->subchannel;
gpr_mu *mu = &c->mu;
@ -472,7 +484,7 @@ static void on_state_changed(void *p, int iomgr_success) {
op.on_connectivity_state_change = &sw->closure;
elem = grpc_channel_stack_element(
CHANNEL_STACK_FROM_CONNECTION(c->active), 0);
elem->filter->start_transport_op(elem, &op);
elem->filter->start_transport_op(exec_ctx, elem, &op);
/* early out */
gpr_mu_unlock(mu);
return;
@ -483,27 +495,28 @@ static void on_state_changed(void *p, int iomgr_success) {
destroy_connection = sw->subchannel->active;
}
sw->subchannel->active = NULL;
grpc_connectivity_state_set(
&c->state_tracker, c->disconnected ? GRPC_CHANNEL_FATAL_FAILURE
: GRPC_CHANNEL_TRANSIENT_FAILURE,
"connection_failed");
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
c->disconnected
? GRPC_CHANNEL_FATAL_FAILURE
: GRPC_CHANNEL_TRANSIENT_FAILURE,
"connection_failed");
break;
}
done:
connectivity_state_changed_locked(c, "transport_state_changed");
connectivity_state_changed_locked(exec_ctx, c, "transport_state_changed");
destroy = SUBCHANNEL_UNREF_LOCKED(c, "state_watcher");
gpr_free(sw);
gpr_mu_unlock(mu);
if (destroy) {
subchannel_destroy(c);
subchannel_destroy(exec_ctx, c);
}
if (destroy_connection != NULL) {
connection_destroy(destroy_connection);
connection_destroy(exec_ctx, destroy_connection);
}
}
static void publish_transport(grpc_subchannel *c) {
static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
size_t channel_stack_size;
connection *con;
grpc_channel_stack *stk;
@ -518,8 +531,8 @@ static void publish_transport(grpc_subchannel *c) {
/* build final filter list */
num_filters = c->num_filters + c->connecting_result.num_filters + 1;
filters = gpr_malloc(sizeof(*filters) * num_filters);
memcpy(filters, c->filters, sizeof(*filters) * c->num_filters);
memcpy(filters + c->num_filters, c->connecting_result.filters,
memcpy((void *)filters, c->filters, sizeof(*filters) * c->num_filters);
memcpy((void *)(filters + c->num_filters), c->connecting_result.filters,
sizeof(*filters) * c->connecting_result.num_filters);
filters[num_filters - 1] = &grpc_connected_channel_filter;
@ -529,15 +542,15 @@ static void publish_transport(grpc_subchannel *c) {
stk = (grpc_channel_stack *)(con + 1);
con->refs = 0;
con->subchannel = c;
grpc_channel_stack_init(filters, num_filters, c->master, c->args, c->mdctx,
stk);
grpc_channel_stack_init(exec_ctx, filters, num_filters, c->master, c->args,
c->mdctx, stk);
grpc_connected_channel_bind_transport(stk, c->connecting_result.transport);
gpr_free(c->connecting_result.filters);
gpr_free((void *)c->connecting_result.filters);
memset(&c->connecting_result, 0, sizeof(c->connecting_result));
/* initialize state watcher */
sw = gpr_malloc(sizeof(*sw));
grpc_iomgr_closure_init(&sw->closure, on_state_changed, sw);
grpc_closure_init(&sw->closure, on_state_changed, sw);
sw->subchannel = c;
sw->connectivity_state = GRPC_CHANNEL_READY;
@ -546,10 +559,10 @@ static void publish_transport(grpc_subchannel *c) {
if (c->disconnected) {
gpr_mu_unlock(&c->mu);
gpr_free(sw);
gpr_free(filters);
grpc_channel_stack_destroy(stk);
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_SUBCHANNEL_UNREF(c, "connecting");
gpr_free((void *)filters);
grpc_channel_stack_destroy(exec_ctx, stk);
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->master, "connecting");
GRPC_SUBCHANNEL_UNREF(exec_ctx, c, "connecting");
return;
}
@ -569,25 +582,29 @@ static void publish_transport(grpc_subchannel *c) {
op.on_connectivity_state_change = &sw->closure;
op.bind_pollset_set = c->pollset_set;
SUBCHANNEL_REF_LOCKED(c, "state_watcher");
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->master, "connecting");
GPR_ASSERT(!SUBCHANNEL_UNREF_LOCKED(c, "connecting"));
elem =
grpc_channel_stack_element(CHANNEL_STACK_FROM_CONNECTION(c->active), 0);
elem->filter->start_transport_op(elem, &op);
elem->filter->start_transport_op(exec_ctx, elem, &op);
/* signal completion */
connectivity_state_changed_locked(c, "connected");
while ((w4c = c->waiting)) {
c->waiting = w4c->next;
grpc_iomgr_add_callback(&w4c->continuation);
}
connectivity_state_changed_locked(exec_ctx, c, "connected");
w4c = c->waiting;
c->waiting = NULL;
gpr_mu_unlock(&c->mu);
gpr_free(filters);
while (w4c != NULL) {
waiting_for_connect *next = w4c->next;
grpc_exec_ctx_enqueue(exec_ctx, &w4c->continuation, 1);
w4c = next;
}
gpr_free((void *)filters);
if (destroy_connection != NULL) {
connection_destroy(destroy_connection);
connection_destroy(exec_ctx, destroy_connection);
}
}
@ -620,35 +637,36 @@ static void update_reconnect_parameters(grpc_subchannel *c) {
gpr_time_add(c->next_attempt, gpr_time_from_millis(jitter, GPR_TIMESPAN));
}
static void on_alarm(void *arg, int iomgr_success) {
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, int iomgr_success) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
c->have_alarm = 0;
if (c->disconnected) {
iomgr_success = 0;
}
connectivity_state_changed_locked(c, "alarm");
connectivity_state_changed_locked(exec_ctx, c, "alarm");
gpr_mu_unlock(&c->mu);
if (iomgr_success) {
update_reconnect_parameters(c);
continue_connect(c);
continue_connect(exec_ctx, c);
} else {
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
GRPC_SUBCHANNEL_UNREF(c, "connecting");
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, c->master, "connecting");
GRPC_SUBCHANNEL_UNREF(exec_ctx, c, "connecting");
}
}
static void subchannel_connected(void *arg, int iomgr_success) {
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_success) {
grpc_subchannel *c = arg;
if (c->connecting_result.transport != NULL) {
publish_transport(c);
publish_transport(exec_ctx, c);
} else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1;
connectivity_state_changed_locked(c, "connect_failed");
grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, now);
connectivity_state_changed_locked(exec_ctx, c, "connect_failed");
grpc_alarm_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
gpr_mu_unlock(&c->mu);
}
}
@ -680,10 +698,11 @@ static grpc_connectivity_state compute_connectivity_locked(grpc_subchannel *c) {
return GRPC_CHANNEL_IDLE;
}
static void connectivity_state_changed_locked(grpc_subchannel *c,
static void connectivity_state_changed_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c,
const char *reason) {
grpc_connectivity_state current = compute_connectivity_locked(c);
grpc_connectivity_state_set(&c->state_tracker, current, reason);
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, current, reason);
}
/*
@ -695,42 +714,46 @@ void grpc_subchannel_call_ref(
gpr_ref(&c->refs);
}
void grpc_subchannel_call_unref(
grpc_subchannel_call *c GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *c
GRPC_SUBCHANNEL_REF_EXTRA_ARGS) {
if (gpr_unref(&c->refs)) {
gpr_mu *mu = &c->connection->subchannel->mu;
grpc_subchannel *destroy;
grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(c));
grpc_call_stack_destroy(exec_ctx, SUBCHANNEL_CALL_TO_CALL_STACK(c));
gpr_mu_lock(mu);
destroy = CONNECTION_UNREF_LOCKED(c->connection, "call");
destroy = CONNECTION_UNREF_LOCKED(exec_ctx, c->connection, "call");
gpr_mu_unlock(mu);
gpr_free(c);
if (destroy != NULL) {
subchannel_destroy(destroy);
subchannel_destroy(exec_ctx, destroy);
}
}
}
char *grpc_subchannel_call_get_peer(grpc_subchannel_call *call) {
char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *call) {
grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
return top_elem->filter->get_peer(top_elem);
return top_elem->filter->get_peer(exec_ctx, top_elem);
}
void grpc_subchannel_call_process_op(grpc_subchannel_call *call,
void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *call,
grpc_transport_stream_op *op) {
grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
top_elem->filter->start_transport_stream_op(top_elem, op);
top_elem->filter->start_transport_stream_op(exec_ctx, top_elem, op);
}
grpc_subchannel_call *create_call(connection *con) {
static grpc_subchannel_call *create_call(grpc_exec_ctx *exec_ctx,
connection *con) {
grpc_channel_stack *chanstk = CHANNEL_STACK_FROM_CONNECTION(con);
grpc_subchannel_call *call =
gpr_malloc(sizeof(grpc_subchannel_call) + chanstk->call_stack_size);
grpc_call_stack *callstk = SUBCHANNEL_CALL_TO_CALL_STACK(call);
call->connection = con;
gpr_ref_init(&call->refs, 1);
grpc_call_stack_init(chanstk, NULL, NULL, callstk);
grpc_call_stack_init(exec_ctx, chanstk, NULL, NULL, callstk);
return call;
}

@ -36,6 +36,7 @@
#include "src/core/channel/channel_stack.h"
#include "src/core/client_config/connector.h"
#include "src/core/transport/connectivity_state.h"
/** A (sub-)channel that knows how to connect to exactly one target
address. Provides a target for load balancing. */
@ -46,39 +47,44 @@ typedef struct grpc_subchannel_args grpc_subchannel_args;
#ifdef GRPC_SUBCHANNEL_REFCOUNT_DEBUG
#define GRPC_SUBCHANNEL_REF(p, r) \
grpc_subchannel_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_UNREF(p, r) \
grpc_subchannel_unref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_UNREF(cl, p, r) \
grpc_subchannel_unref((cl), (p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_CALL_REF(p, r) \
grpc_subchannel_call_ref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) \
grpc_subchannel_call_unref((p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
grpc_subchannel_call_unref((cl), (p), __FILE__, __LINE__, (r))
#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \
, const char *file, int line, const char *reason
#else
#define GRPC_SUBCHANNEL_REF(p, r) grpc_subchannel_ref((p))
#define GRPC_SUBCHANNEL_UNREF(p, r) grpc_subchannel_unref((p))
#define GRPC_SUBCHANNEL_UNREF(cl, p, r) grpc_subchannel_unref((cl), (p))
#define GRPC_SUBCHANNEL_CALL_REF(p, r) grpc_subchannel_call_ref((p))
#define GRPC_SUBCHANNEL_CALL_UNREF(p, r) grpc_subchannel_call_unref((p))
#define GRPC_SUBCHANNEL_CALL_UNREF(cl, p, r) \
grpc_subchannel_call_unref((cl), (p))
#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS
#endif
void grpc_subchannel_ref(
grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_unref(
grpc_subchannel *channel GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel *channel
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_call_ref(
grpc_subchannel_call *call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_call_unref(
grpc_subchannel_call *call GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
void grpc_subchannel_call_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *call
GRPC_SUBCHANNEL_REF_EXTRA_ARGS);
/** construct a call (possibly asynchronously) */
void grpc_subchannel_create_call(grpc_subchannel *subchannel,
void grpc_subchannel_create_call(grpc_exec_ctx *exec_ctx,
grpc_subchannel *subchannel,
grpc_pollset *pollset,
grpc_subchannel_call **target,
grpc_iomgr_closure *notify);
grpc_closure *notify);
/** process a transport level op */
void grpc_subchannel_process_transport_op(grpc_subchannel *subchannel,
void grpc_subchannel_process_transport_op(grpc_exec_ctx *exec_ctx,
grpc_subchannel *subchannel,
grpc_transport_op *op);
/** poll the current connectivity state of a channel */
@ -87,23 +93,28 @@ grpc_connectivity_state grpc_subchannel_check_connectivity(
/** call notify when the connectivity state of a channel changes from *state.
Updates *state with the new state of the channel */
void grpc_subchannel_notify_on_state_change(grpc_subchannel *channel,
void grpc_subchannel_notify_on_state_change(grpc_exec_ctx *exec_ctx,
grpc_subchannel *channel,
grpc_connectivity_state *state,
grpc_iomgr_closure *notify);
grpc_closure *notify);
/** express interest in \a channel's activities through \a pollset. */
void grpc_subchannel_add_interested_party(grpc_subchannel *channel,
void grpc_subchannel_add_interested_party(grpc_exec_ctx *exec_ctx,
grpc_subchannel *channel,
grpc_pollset *pollset);
/** stop following \a channel's activity through \a pollset. */
void grpc_subchannel_del_interested_party(grpc_subchannel *channel,
void grpc_subchannel_del_interested_party(grpc_exec_ctx *exec_ctx,
grpc_subchannel *channel,
grpc_pollset *pollset);
/** continue processing a transport op */
void grpc_subchannel_call_process_op(grpc_subchannel_call *subchannel_call,
void grpc_subchannel_call_process_op(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *subchannel_call,
grpc_transport_stream_op *op);
/** continue querying for peer */
char *grpc_subchannel_call_get_peer(grpc_subchannel_call *subchannel_call);
char *grpc_subchannel_call_get_peer(grpc_exec_ctx *exec_ctx,
grpc_subchannel_call *subchannel_call);
struct grpc_subchannel_args {
/** Channel filters for this channel - wrapped factories will likely

@ -33,14 +33,17 @@
#include "src/core/client_config/subchannel_factory.h"
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory) {
void grpc_subchannel_factory_ref(grpc_subchannel_factory* factory) {
factory->vtable->ref(factory);
}
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory) {
factory->vtable->unref(factory);
void grpc_subchannel_factory_unref(grpc_exec_ctx* exec_ctx,
grpc_subchannel_factory* factory) {
factory->vtable->unref(exec_ctx, factory);
}
grpc_subchannel *grpc_subchannel_factory_create_subchannel(
grpc_subchannel_factory *factory, grpc_subchannel_args *args) {
return factory->vtable->create_subchannel(factory, args);
grpc_subchannel* grpc_subchannel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_subchannel_factory* factory,
grpc_subchannel_args* args) {
return factory->vtable->create_subchannel(exec_ctx, factory, args);
}

@ -48,16 +48,19 @@ struct grpc_subchannel_factory {
struct grpc_subchannel_factory_vtable {
void (*ref)(grpc_subchannel_factory *factory);
void (*unref)(grpc_subchannel_factory *factory);
grpc_subchannel *(*create_subchannel)(grpc_subchannel_factory *factory,
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory);
grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *factory,
grpc_subchannel_args *args);
};
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory);
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory);
void grpc_subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *factory);
/** Create a new grpc_subchannel */
grpc_subchannel *grpc_subchannel_factory_create_subchannel(
grpc_subchannel_factory *factory, grpc_subchannel_args *args);
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
grpc_subchannel_args *args);
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H */

@ -43,4 +43,4 @@ grpc_subchannel_factory *grpc_subchannel_factory_add_channel_arg(
grpc_subchannel_factory *input, const grpc_arg *arg);
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_ADD_CHANNEL_ARG_H \
*/
*/

@ -47,23 +47,25 @@ static void merge_args_factory_ref(grpc_subchannel_factory *scf) {
gpr_ref(&f->refs);
}
static void merge_args_factory_unref(grpc_subchannel_factory *scf) {
static void merge_args_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *scf) {
merge_args_factory *f = (merge_args_factory *)scf;
if (gpr_unref(&f->refs)) {
grpc_subchannel_factory_unref(f->wrapped);
grpc_subchannel_factory_unref(exec_ctx, f->wrapped);
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}
}
static grpc_subchannel *merge_args_factory_create_subchannel(
grpc_subchannel_factory *scf, grpc_subchannel_args *args) {
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
grpc_subchannel_args *args) {
merge_args_factory *f = (merge_args_factory *)scf;
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
grpc_subchannel *s;
args->args = final_args;
s = grpc_subchannel_factory_create_subchannel(f->wrapped, args);
s = grpc_subchannel_factory_create_subchannel(exec_ctx, f->wrapped, args);
grpc_channel_args_destroy(final_args);
return s;
}

@ -43,4 +43,4 @@ grpc_subchannel_factory *grpc_subchannel_factory_merge_channel_args(
grpc_subchannel_factory *input, const grpc_channel_args *args);
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_DECORATORS_MERGE_CHANNEL_ARGS_H \
*/
*/

@ -79,12 +79,11 @@ static size_t parse_pchar(const char *uri_text, size_t i) {
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* pct-encoded = "%" HEXDIG HEXDIG
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "=" */
/ "*" / "+" / "," / ";" / "=" */
char c = uri_text[i];
if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
((c >= '0') && (c <= '9')) ||
(c == '-' || c == '.' || c == '_' || c == '~') || /* unreserved */
(c == '!' || c == '$' || c == '&' || c == '\'' || c == '$' || c == '&' ||
c == '(' || c == ')' || c == '*' || c == '+' || c == ',' || c == ';' ||
c == '=') /* sub-delims */) {

@ -106,7 +106,7 @@ grpc_compression_level grpc_compression_level_for_algorithm(
}
void grpc_compression_options_init(grpc_compression_options *opts) {
opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT)-1;
opts->enabled_algorithms_bitset = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
opts->default_compression_algorithm = GRPC_COMPRESS_NONE;
}

@ -42,9 +42,9 @@
#define OUTPUT_BLOCK_SIZE 1024
static int zlib_body(z_stream *zs, gpr_slice_buffer *input,
gpr_slice_buffer *output,
int (*flate)(z_stream *zs, int flush)) {
static int zlib_body(z_stream* zs, gpr_slice_buffer* input,
gpr_slice_buffer* output,
int (*flate)(z_stream* zs, int flush)) {
int r;
int flush;
size_t i;
@ -91,7 +91,7 @@ error:
return 0;
}
static int zlib_compress(gpr_slice_buffer *input, gpr_slice_buffer *output,
static int zlib_compress(gpr_slice_buffer* input, gpr_slice_buffer* output,
int gzip) {
z_stream zs;
int r;
@ -117,7 +117,7 @@ static int zlib_compress(gpr_slice_buffer *input, gpr_slice_buffer *output,
return r;
}
static int zlib_decompress(gpr_slice_buffer *input, gpr_slice_buffer *output,
static int zlib_decompress(gpr_slice_buffer* input, gpr_slice_buffer* output,
int gzip) {
z_stream zs;
int r;
@ -142,7 +142,7 @@ static int zlib_decompress(gpr_slice_buffer *input, gpr_slice_buffer *output,
return r;
}
static int copy(gpr_slice_buffer *input, gpr_slice_buffer *output) {
static int copy(gpr_slice_buffer* input, gpr_slice_buffer* output) {
size_t i;
for (i = 0; i < input->count; i++) {
gpr_slice_buffer_add(output, gpr_slice_ref(input->slices[i]));
@ -151,7 +151,7 @@ static int copy(gpr_slice_buffer *input, gpr_slice_buffer *output) {
}
int compress_inner(grpc_compression_algorithm algorithm,
gpr_slice_buffer *input, gpr_slice_buffer *output) {
gpr_slice_buffer* input, gpr_slice_buffer* output) {
switch (algorithm) {
case GRPC_COMPRESS_NONE:
/* the fallback path always needs to be send uncompressed: we simply
@ -169,7 +169,7 @@ int compress_inner(grpc_compression_algorithm algorithm,
}
int grpc_msg_compress(grpc_compression_algorithm algorithm,
gpr_slice_buffer *input, gpr_slice_buffer *output) {
gpr_slice_buffer* input, gpr_slice_buffer* output) {
if (!compress_inner(algorithm, input, output)) {
copy(input, output);
return 0;
@ -178,7 +178,7 @@ int grpc_msg_compress(grpc_compression_algorithm algorithm,
}
int grpc_msg_decompress(grpc_compression_algorithm algorithm,
gpr_slice_buffer *input, gpr_slice_buffer *output) {
gpr_slice_buffer* input, gpr_slice_buffer* output) {
switch (algorithm) {
case GRPC_COMPRESS_NONE:
return copy(input, output);

@ -41,12 +41,12 @@
On success, appends compressed slices to output and returns 1.
On failure, appends uncompressed slices to output and returns 0. */
int grpc_msg_compress(grpc_compression_algorithm algorithm,
gpr_slice_buffer *input, gpr_slice_buffer *output);
gpr_slice_buffer* input, gpr_slice_buffer* output);
/* decompress 'input' to 'output' using 'algorithm'.
On success, appends slices to output and returns 1.
On failure, output is unchanged, and returns 0. */
int grpc_msg_decompress(grpc_compression_algorithm algorithm,
gpr_slice_buffer *input, gpr_slice_buffer *output);
gpr_slice_buffer* input, gpr_slice_buffer* output);
#endif /* GRPC_INTERNAL_CORE_COMPRESSION_MESSAGE_COMPRESS_H */

@ -63,18 +63,20 @@ typedef struct {
grpc_iomgr_object iomgr_obj;
gpr_slice_buffer incoming;
gpr_slice_buffer outgoing;
grpc_iomgr_closure on_read;
grpc_iomgr_closure done_write;
grpc_closure on_read;
grpc_closure done_write;
grpc_closure connected;
} internal_request;
static grpc_httpcli_get_override g_get_override = NULL;
static grpc_httpcli_post_override g_post_override = NULL;
static void plaintext_handshake(void *arg, grpc_endpoint *endpoint,
const char *host,
void (*on_done)(void *arg,
static void plaintext_handshake(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint, const char *host,
void (*on_done)(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_endpoint *endpoint)) {
on_done(arg, endpoint);
on_done(exec_ctx, arg, endpoint);
}
const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http",
@ -88,17 +90,19 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context) {
grpc_pollset_set_destroy(&context->pollset_set);
}
static void next_address(internal_request *req);
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req);
static void finish(internal_request *req, int success) {
grpc_pollset_set_del_pollset(&req->context->pollset_set, req->pollset);
req->on_response(req->user_data, success ? &req->parser.r : NULL);
static void finish(grpc_exec_ctx *exec_ctx, internal_request *req,
int success) {
grpc_pollset_set_del_pollset(exec_ctx, &req->context->pollset_set,
req->pollset);
req->on_response(exec_ctx, req->user_data, success ? &req->parser.r : NULL);
grpc_httpcli_parser_destroy(&req->parser);
if (req->addresses != NULL) {
grpc_resolved_addresses_destroy(req->addresses);
}
if (req->ep != NULL) {
grpc_endpoint_destroy(req->ep);
grpc_endpoint_destroy(exec_ctx, req->ep);
}
gpr_slice_unref(req->request_text);
gpr_free(req->host);
@ -108,22 +112,13 @@ static void finish(internal_request *req, int success) {
gpr_free(req);
}
static void on_read(void *user_data, int success);
static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, int success);
static void do_read(internal_request *req) {
switch (grpc_endpoint_read(req->ep, &req->incoming, &req->on_read)) {
case GRPC_ENDPOINT_DONE:
on_read(req, 1);
break;
case GRPC_ENDPOINT_PENDING:
break;
case GRPC_ENDPOINT_ERROR:
on_read(req, 0);
break;
}
static void do_read(grpc_exec_ctx *exec_ctx, internal_request *req) {
grpc_endpoint_read(exec_ctx, req->ep, &req->incoming, &req->on_read);
}
static void on_read(void *user_data, int success) {
static void on_read(grpc_exec_ctx *exec_ctx, void *user_data, int success) {
internal_request *req = user_data;
size_t i;
@ -131,105 +126,97 @@ static void on_read(void *user_data, int success) {
if (GPR_SLICE_LENGTH(req->incoming.slices[i])) {
req->have_read_byte = 1;
if (!grpc_httpcli_parser_parse(&req->parser, req->incoming.slices[i])) {
finish(req, 0);
finish(exec_ctx, req, 0);
return;
}
}
}
if (success) {
do_read(req);
do_read(exec_ctx, req);
} else if (!req->have_read_byte) {
next_address(req);
next_address(exec_ctx, req);
} else {
finish(req, grpc_httpcli_parser_eof(&req->parser));
finish(exec_ctx, req, grpc_httpcli_parser_eof(&req->parser));
}
}
static void on_written(internal_request *req) { do_read(req); }
static void on_written(grpc_exec_ctx *exec_ctx, internal_request *req) {
do_read(exec_ctx, req);
}
static void done_write(void *arg, int success) {
static void done_write(grpc_exec_ctx *exec_ctx, void *arg, int success) {
internal_request *req = arg;
if (success) {
on_written(req);
on_written(exec_ctx, req);
} else {
next_address(req);
next_address(exec_ctx, req);
}
}
static void start_write(internal_request *req) {
static void start_write(grpc_exec_ctx *exec_ctx, internal_request *req) {
gpr_slice_ref(req->request_text);
gpr_slice_buffer_add(&req->outgoing, req->request_text);
switch (grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write)) {
case GRPC_ENDPOINT_DONE:
on_written(req);
break;
case GRPC_ENDPOINT_PENDING:
break;
case GRPC_ENDPOINT_ERROR:
finish(req, 0);
break;
}
grpc_endpoint_write(exec_ctx, req->ep, &req->outgoing, &req->done_write);
}
static void on_handshake_done(void *arg, grpc_endpoint *ep) {
static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *ep) {
internal_request *req = arg;
if (!ep) {
next_address(req);
next_address(exec_ctx, req);
return;
}
req->ep = ep;
start_write(req);
start_write(exec_ctx, req);
}
static void on_connected(void *arg, grpc_endpoint *tcp) {
static void on_connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
internal_request *req = arg;
if (!tcp) {
next_address(req);
if (!req->ep) {
next_address(exec_ctx, req);
return;
}
req->handshaker->handshake(req, tcp, req->host, on_handshake_done);
req->handshaker->handshake(exec_ctx, req, req->ep, req->host,
on_handshake_done);
}
static void next_address(internal_request *req) {
static void next_address(grpc_exec_ctx *exec_ctx, internal_request *req) {
grpc_resolved_address *addr;
if (req->next_address == req->addresses->naddrs) {
finish(req, 0);
finish(exec_ctx, req, 0);
return;
}
addr = &req->addresses->addrs[req->next_address++];
grpc_tcp_client_connect(on_connected, req, &req->context->pollset_set,
(struct sockaddr *)&addr->addr, addr->len,
req->deadline);
grpc_closure_init(&req->connected, on_connected, req);
grpc_tcp_client_connect(
exec_ctx, &req->connected, &req->ep, &req->context->pollset_set,
(struct sockaddr *)&addr->addr, addr->len, req->deadline);
}
static void on_resolved(void *arg, grpc_resolved_addresses *addresses) {
static void on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
internal_request *req = arg;
if (!addresses) {
finish(req, 0);
finish(exec_ctx, req, 0);
return;
}
req->addresses = addresses;
req->next_address = 0;
next_address(req);
next_address(exec_ctx, req);
}
void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
internal_request *req;
char *name;
if (g_get_override &&
g_get_override(request, deadline, on_response, user_data)) {
return;
}
req = gpr_malloc(sizeof(internal_request));
static void internal_request_begin(
grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset, const grpc_httpcli_request *request,
gpr_timespec deadline, grpc_httpcli_response_cb on_response,
void *user_data, const char *name, gpr_slice request_text) {
internal_request *req = gpr_malloc(sizeof(internal_request));
memset(req, 0, sizeof(*req));
req->request_text = grpc_httpcli_format_get_request(request);
req->request_text = request_text;
grpc_httpcli_parser_init(&req->parser);
req->on_response = on_response;
req->user_data = user_data;
@ -238,55 +225,53 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
req->context = context;
req->pollset = pollset;
grpc_iomgr_closure_init(&req->on_read, on_read, req);
grpc_iomgr_closure_init(&req->done_write, done_write, req);
grpc_closure_init(&req->on_read, on_read, req);
grpc_closure_init(&req->done_write, done_write, req);
gpr_slice_buffer_init(&req->incoming);
gpr_slice_buffer_init(&req->outgoing);
gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path);
grpc_iomgr_register_object(&req->iomgr_obj, name);
gpr_free(name);
req->host = gpr_strdup(request->host);
grpc_pollset_set_add_pollset(&req->context->pollset_set, req->pollset);
grpc_pollset_set_add_pollset(exec_ctx, &req->context->pollset_set,
req->pollset);
grpc_resolve_address(request->host, req->handshaker->default_port,
on_resolved, req);
}
void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset,
void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
char *name;
if (g_get_override &&
g_get_override(exec_ctx, request, deadline, on_response, user_data)) {
return;
}
gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path);
internal_request_begin(exec_ctx, context, pollset, request, deadline,
on_response, user_data, name,
grpc_httpcli_format_get_request(request));
gpr_free(name);
}
void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset,
const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data) {
internal_request *req;
char *name;
if (g_post_override && g_post_override(request, body_bytes, body_size,
deadline, on_response, user_data)) {
if (g_post_override &&
g_post_override(exec_ctx, request, body_bytes, body_size, deadline,
on_response, user_data)) {
return;
}
req = gpr_malloc(sizeof(internal_request));
memset(req, 0, sizeof(*req));
req->request_text =
grpc_httpcli_format_post_request(request, body_bytes, body_size);
grpc_httpcli_parser_init(&req->parser);
req->on_response = on_response;
req->user_data = user_data;
req->deadline = deadline;
req->handshaker =
request->handshaker ? request->handshaker : &grpc_httpcli_plaintext;
req->context = context;
req->pollset = pollset;
grpc_iomgr_closure_init(&req->on_read, on_read, req);
grpc_iomgr_closure_init(&req->done_write, done_write, req);
gpr_slice_buffer_init(&req->incoming);
gpr_slice_buffer_init(&req->outgoing);
gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->path);
grpc_iomgr_register_object(&req->iomgr_obj, name);
internal_request_begin(
exec_ctx, context, pollset, request, deadline, on_response, user_data,
name, grpc_httpcli_format_post_request(request, body_bytes, body_size));
gpr_free(name);
req->host = gpr_strdup(request->host);
grpc_pollset_set_add_pollset(&req->context->pollset_set, req->pollset);
grpc_resolve_address(request->host, req->handshaker->default_port,
on_resolved, req);
}
void grpc_httpcli_set_override(grpc_httpcli_get_override get,

@ -61,8 +61,10 @@ typedef struct grpc_httpcli_context {
typedef struct {
const char *default_port;
void (*handshake)(void *arg, grpc_endpoint *endpoint, const char *host,
void (*on_done)(void *arg, grpc_endpoint *endpoint));
void (*handshake)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint,
const char *host,
void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint));
} grpc_httpcli_handshaker;
extern const grpc_httpcli_handshaker grpc_httpcli_plaintext;
@ -76,7 +78,7 @@ typedef struct grpc_httpcli_request {
char *path;
/* Additional headers: count and key/values; the following are supplied
automatically and MUST NOT be set here:
Host, Connection, User-Agent */
Host, Connection, User-Agent */
size_t hdr_count;
grpc_httpcli_header *hdrs;
/* handshaker to use ssl for the request */
@ -96,7 +98,8 @@ typedef struct grpc_httpcli_response {
} grpc_httpcli_response;
/* Callback for grpc_httpcli_get and grpc_httpcli_post. */
typedef void (*grpc_httpcli_response_cb)(void *user_data,
typedef void (*grpc_httpcli_response_cb)(grpc_exec_ctx *exec_ctx,
void *user_data,
const grpc_httpcli_response *response);
void grpc_httpcli_context_init(grpc_httpcli_context *context);
@ -112,7 +115,8 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context *context);
'deadline' contains a deadline for the request (or gpr_inf_future)
'on_response' is a callback to report results to (and 'user_data' is a user
supplied pointer to pass to said call) */
void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
void grpc_httpcli_get(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data);
@ -132,23 +136,23 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset,
'on_response' is a callback to report results to (and 'user_data' is a user
supplied pointer to pass to said call)
Does not support ?var1=val1&var2=val2 in the path. */
void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset,
void grpc_httpcli_post(grpc_exec_ctx *exec_ctx, grpc_httpcli_context *context,
grpc_pollset *pollset,
const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data);
/* override functions return 1 if they handled the request, 0 otherwise */
typedef int (*grpc_httpcli_get_override)(const grpc_httpcli_request *request,
typedef int (*grpc_httpcli_get_override)(grpc_exec_ctx *exec_ctx,
const grpc_httpcli_request *request,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data);
typedef int (*grpc_httpcli_post_override)(const grpc_httpcli_request *request,
const char *body_bytes,
size_t body_size,
gpr_timespec deadline,
grpc_httpcli_response_cb on_response,
void *user_data);
typedef int (*grpc_httpcli_post_override)(
grpc_exec_ctx *exec_ctx, const grpc_httpcli_request *request,
const char *body_bytes, size_t body_size, gpr_timespec deadline,
grpc_httpcli_response_cb on_response, void *user_data);
void grpc_httpcli_set_override(grpc_httpcli_get_override get,
grpc_httpcli_post_override post);

@ -58,15 +58,17 @@ static void httpcli_ssl_destroy(grpc_security_connector *sc) {
gpr_free(sc);
}
static void httpcli_ssl_do_handshake(
grpc_security_connector *sc, grpc_endpoint *nonsecure_endpoint,
grpc_security_handshake_done_cb cb, void *user_data) {
static void httpcli_ssl_do_handshake(grpc_exec_ctx *exec_ctx,
grpc_security_connector *sc,
grpc_endpoint *nonsecure_endpoint,
grpc_security_handshake_done_cb cb,
void *user_data) {
grpc_httpcli_ssl_channel_security_connector *c =
(grpc_httpcli_ssl_channel_security_connector *)sc;
tsi_result result = TSI_OK;
tsi_handshaker *handshaker;
if (c->handshaker_factory == NULL) {
cb(user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
return;
}
result = tsi_ssl_handshaker_factory_create_handshaker(
@ -74,9 +76,9 @@ static void httpcli_ssl_do_handshake(
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker creation failed with error %s.",
tsi_result_to_string(result));
cb(user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
cb(exec_ctx, user_data, GRPC_SECURITY_ERROR, nonsecure_endpoint, NULL);
} else {
grpc_do_security_handshake(handshaker, sc, nonsecure_endpoint, cb,
grpc_do_security_handshake(exec_ctx, handshaker, sc, nonsecure_endpoint, cb,
user_data);
}
}
@ -141,33 +143,35 @@ static grpc_security_status httpcli_ssl_channel_security_connector_create(
/* handshaker */
typedef struct {
void (*func)(void *arg, grpc_endpoint *endpoint);
void (*func)(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *endpoint);
void *arg;
} on_done_closure;
static void on_secure_transport_setup_done(void *rp,
static void on_secure_transport_setup_done(grpc_exec_ctx *exec_ctx, void *rp,
grpc_security_status status,
grpc_endpoint *wrapped_endpoint,
grpc_endpoint *secure_endpoint) {
on_done_closure *c = rp;
if (status != GRPC_SECURITY_OK) {
gpr_log(GPR_ERROR, "Secure transport setup failed with error %d.", status);
c->func(c->arg, NULL);
c->func(exec_ctx, c->arg, NULL);
} else {
c->func(c->arg, secure_endpoint);
c->func(exec_ctx, c->arg, secure_endpoint);
}
gpr_free(c);
}
static void ssl_handshake(void *arg, grpc_endpoint *tcp, const char *host,
void (*on_done)(void *arg, grpc_endpoint *endpoint)) {
static void ssl_handshake(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *tcp, const char *host,
void (*on_done)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *endpoint)) {
grpc_channel_security_connector *sc = NULL;
const unsigned char *pem_root_certs = NULL;
on_done_closure *c = gpr_malloc(sizeof(*c));
size_t pem_root_certs_size = grpc_get_default_ssl_roots(&pem_root_certs);
if (pem_root_certs == NULL || pem_root_certs_size == 0) {
gpr_log(GPR_ERROR, "Could not get default pem root certs.");
on_done(arg, NULL);
on_done(exec_ctx, arg, NULL);
gpr_free(c);
return;
}
@ -176,7 +180,7 @@ static void ssl_handshake(void *arg, grpc_endpoint *tcp, const char *host,
GPR_ASSERT(httpcli_ssl_channel_security_connector_create(
pem_root_certs, pem_root_certs_size, host, &sc) ==
GRPC_SECURITY_OK);
grpc_security_connector_do_handshake(&sc->base, tcp,
grpc_security_connector_do_handshake(exec_ctx, &sc->base, tcp,
on_secure_transport_setup_done, c);
GRPC_SECURITY_CONNECTOR_UNREF(&sc->base, "httpcli");
}

@ -55,10 +55,10 @@ typedef struct {
size_t cur_line_length;
} grpc_httpcli_parser;
void grpc_httpcli_parser_init(grpc_httpcli_parser *parser);
void grpc_httpcli_parser_destroy(grpc_httpcli_parser *parser);
void grpc_httpcli_parser_init(grpc_httpcli_parser* parser);
void grpc_httpcli_parser_destroy(grpc_httpcli_parser* parser);
int grpc_httpcli_parser_parse(grpc_httpcli_parser *parser, gpr_slice slice);
int grpc_httpcli_parser_eof(grpc_httpcli_parser *parser);
int grpc_httpcli_parser_parse(grpc_httpcli_parser* parser, gpr_slice slice);
int grpc_httpcli_parser_eof(grpc_httpcli_parser* parser);
#endif /* GRPC_INTERNAL_CORE_HTTPCLI_PARSER_H */

@ -44,7 +44,6 @@
#define LOG2_NUM_SHARDS 5
#define NUM_SHARDS (1 << LOG2_NUM_SHARDS)
#define MAX_ALARMS_PER_CHECK 128
#define ADD_DEADLINE_SCALE 0.33
#define MIN_QUEUE_WINDOW_DURATION 0.01
#define MAX_QUEUE_WINDOW_DURATION 1
@ -73,7 +72,7 @@ static shard_type g_shards[NUM_SHARDS];
/* Protected by g_mu */
static shard_type *g_shard_queue[NUM_SHARDS];
static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now,
static int run_some_expired_alarms(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_timespec *next, int success);
static gpr_timespec compute_min_deadline(shard_type *shard) {
@ -103,10 +102,9 @@ void grpc_alarm_list_init(gpr_timespec now) {
}
}
void grpc_alarm_list_shutdown(void) {
void grpc_alarm_list_shutdown(grpc_exec_ctx *exec_ctx) {
int i;
while (run_some_expired_alarms(NULL, gpr_inf_future(g_clock_type), NULL, 0))
;
run_some_expired_alarms(exec_ctx, gpr_inf_future(g_clock_type), NULL, 0);
for (i = 0; i < NUM_SHARDS; i++) {
shard_type *shard = &g_shards[i];
gpr_mu_destroy(&shard->mu);
@ -172,15 +170,14 @@ static void note_deadline_change(shard_type *shard) {
}
}
void grpc_alarm_init(grpc_alarm *alarm, gpr_timespec deadline,
grpc_iomgr_cb_func alarm_cb, void *alarm_cb_arg,
gpr_timespec now) {
void grpc_alarm_init(grpc_exec_ctx *exec_ctx, grpc_alarm *alarm,
gpr_timespec deadline, grpc_iomgr_cb_func alarm_cb,
void *alarm_cb_arg, gpr_timespec now) {
int is_first_alarm = 0;
shard_type *shard = &g_shards[shard_idx(alarm)];
GPR_ASSERT(deadline.clock_type == g_clock_type);
GPR_ASSERT(now.clock_type == g_clock_type);
alarm->cb = alarm_cb;
alarm->cb_arg = alarm_cb_arg;
grpc_closure_init(&alarm->closure, alarm_cb, alarm_cb_arg);
alarm->deadline = deadline;
alarm->triggered = 0;
@ -223,12 +220,11 @@ void grpc_alarm_init(grpc_alarm *alarm, gpr_timespec deadline,
}
}
void grpc_alarm_cancel(grpc_alarm *alarm) {
void grpc_alarm_cancel(grpc_exec_ctx *exec_ctx, grpc_alarm *alarm) {
shard_type *shard = &g_shards[shard_idx(alarm)];
int triggered = 0;
gpr_mu_lock(&shard->mu);
if (!alarm->triggered) {
triggered = 1;
grpc_exec_ctx_enqueue(exec_ctx, &alarm->closure, 0);
alarm->triggered = 1;
if (alarm->heap_index == INVALID_HEAP_INDEX) {
list_remove(alarm);
@ -237,10 +233,6 @@ void grpc_alarm_cancel(grpc_alarm *alarm) {
}
}
gpr_mu_unlock(&shard->mu);
if (triggered) {
alarm->cb(alarm->cb_arg, 0);
}
}
/* This is called when the queue is empty and "now" has reached the
@ -291,40 +283,38 @@ static grpc_alarm *pop_one(shard_type *shard, gpr_timespec now) {
}
/* REQUIRES: shard->mu unlocked */
static size_t pop_alarms(shard_type *shard, gpr_timespec now,
grpc_alarm **alarms, size_t max_alarms,
gpr_timespec *new_min_deadline) {
static size_t pop_alarms(grpc_exec_ctx *exec_ctx, shard_type *shard,
gpr_timespec now, gpr_timespec *new_min_deadline,
int success) {
size_t n = 0;
grpc_alarm *alarm;
gpr_mu_lock(&shard->mu);
while (n < max_alarms && (alarm = pop_one(shard, now))) {
alarms[n++] = alarm;
while ((alarm = pop_one(shard, now))) {
grpc_exec_ctx_enqueue(exec_ctx, &alarm->closure, success);
n++;
}
*new_min_deadline = compute_min_deadline(shard);
gpr_mu_unlock(&shard->mu);
return n;
}
static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now,
static int run_some_expired_alarms(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_timespec *next, int success) {
size_t n = 0;
size_t i;
grpc_alarm *alarms[MAX_ALARMS_PER_CHECK];
/* TODO(ctiller): verify that there are any alarms (atomically) here */
if (gpr_mu_trylock(&g_checker_mu)) {
gpr_mu_lock(&g_mu);
while (n < MAX_ALARMS_PER_CHECK &&
gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
while (gpr_time_cmp(g_shard_queue[0]->min_deadline, now) < 0) {
gpr_timespec new_min_deadline;
/* For efficiency, we pop as many available alarms as we can from the
shard. This may violate perfect alarm deadline ordering, but that
shouldn't be a big deal because we don't make ordering guarantees. */
n += pop_alarms(g_shard_queue[0], now, alarms + n,
MAX_ALARMS_PER_CHECK - n, &new_min_deadline);
n += pop_alarms(exec_ctx, g_shard_queue[0], now, &new_min_deadline,
success);
/* An grpc_alarm_init() on the shard could intervene here, adding a new
alarm that is earlier than new_min_deadline. However,
@ -343,25 +333,14 @@ static int run_some_expired_alarms(gpr_mu *drop_mu, gpr_timespec now,
gpr_mu_unlock(&g_checker_mu);
}
if (n && drop_mu) {
gpr_mu_unlock(drop_mu);
}
for (i = 0; i < n; i++) {
alarms[i]->cb(alarms[i]->cb_arg, success);
}
if (n && drop_mu) {
gpr_mu_lock(drop_mu);
}
return (int)n;
}
int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next) {
int grpc_alarm_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_timespec *next) {
GPR_ASSERT(now.clock_type == g_clock_type);
return run_some_expired_alarms(
drop_mu, now, next,
exec_ctx, now, next,
gpr_time_cmp(now, gpr_inf_future(now.clock_type)) != 0);
}

@ -35,6 +35,7 @@
#define GRPC_INTERNAL_CORE_IOMGR_ALARM_H
#include "src/core/iomgr/iomgr.h"
#include "src/core/iomgr/exec_ctx.h"
#include <grpc/support/port_platform.h>
#include <grpc/support/time.h>
@ -44,8 +45,7 @@ typedef struct grpc_alarm {
int triggered;
struct grpc_alarm *next;
struct grpc_alarm *prev;
grpc_iomgr_cb_func cb;
void *cb_arg;
grpc_closure closure;
} grpc_alarm;
/* Initialize *alarm. When expired or canceled, alarm_cb will be called with
@ -54,9 +54,9 @@ typedef struct grpc_alarm {
and application code should check the status to determine how it was
invoked. The application callback is also responsible for maintaining
information about when to free up any user-level state. */
void grpc_alarm_init(grpc_alarm *alarm, gpr_timespec deadline,
grpc_iomgr_cb_func alarm_cb, void *alarm_cb_arg,
gpr_timespec now);
void grpc_alarm_init(grpc_exec_ctx *exec_ctx, grpc_alarm *alarm,
gpr_timespec deadline, grpc_iomgr_cb_func alarm_cb,
void *alarm_cb_arg, gpr_timespec now);
/* Note that there is no alarm destroy function. This is because the
alarm is a one-time occurrence with a guarantee that the callback will
@ -84,6 +84,6 @@ void grpc_alarm_init(grpc_alarm *alarm, gpr_timespec deadline,
matches this aim.
Requires: cancel() must happen after add() on a given alarm */
void grpc_alarm_cancel(grpc_alarm *alarm);
void grpc_alarm_cancel(grpc_exec_ctx *exec_ctx, grpc_alarm *alarm);
#endif /* GRPC_INTERNAL_CORE_IOMGR_ALARM_H */

@ -34,6 +34,7 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_ALARM_INTERNAL_H
#define GRPC_INTERNAL_CORE_IOMGR_ALARM_INTERNAL_H
#include "src/core/iomgr/exec_ctx.h"
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
@ -48,10 +49,10 @@
with high probability at least one thread in the system will see an update
at any time slice. */
int grpc_alarm_check(gpr_mu *drop_mu, gpr_timespec now, gpr_timespec *next);
int grpc_alarm_check(grpc_exec_ctx* exec_ctx, gpr_timespec now,
gpr_timespec* next);
void grpc_alarm_list_init(gpr_timespec now);
void grpc_alarm_list_shutdown(void);
void grpc_alarm_list_shutdown(grpc_exec_ctx* exec_ctx);
gpr_timespec grpc_alarm_list_next_timeout(void);

@ -0,0 +1,71 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/iomgr/closure.h"
void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg) {
closure->cb = cb;
closure->cb_arg = cb_arg;
closure->next = NULL;
}
void grpc_closure_list_add(grpc_closure_list *closure_list,
grpc_closure *closure, int success) {
if (closure == NULL) return;
closure->next = NULL;
closure->success = success;
if (closure_list->head == NULL) {
closure_list->head = closure;
} else {
closure_list->tail->next = closure;
}
closure_list->tail = closure;
}
int grpc_closure_list_empty(grpc_closure_list closure_list) {
return closure_list.head == NULL;
}
void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst) {
if (src->head == NULL) {
return;
}
if (dst->head == NULL) {
*dst = *src;
} else {
dst->tail->next = src->head;
dst->tail = src->tail;
}
src->head = src->tail = NULL;
}

@ -0,0 +1,88 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_CORE_IOMGR_CLOSURE_H
#define GRPC_INTERNAL_CORE_IOMGR_CLOSURE_H
#include <stddef.h>
struct grpc_closure;
typedef struct grpc_closure grpc_closure;
/* forward declaration for exec_ctx.h */
struct grpc_exec_ctx;
typedef struct grpc_exec_ctx grpc_exec_ctx;
typedef struct grpc_closure_list {
grpc_closure *head;
grpc_closure *tail;
} grpc_closure_list;
/** gRPC Callback definition.
*
* \param arg Arbitrary input.
* \param success An indication on the state of the iomgr. On false, cleanup
* actions should be taken (eg, shutdown). */
typedef void (*grpc_iomgr_cb_func)(grpc_exec_ctx *exec_ctx, void *arg,
int success);
/** A closure over a grpc_iomgr_cb_func. */
struct grpc_closure {
/** Bound callback. */
grpc_iomgr_cb_func cb;
/** Arguments to be passed to "cb". */
void *cb_arg;
/** Internal. A boolean indication to "cb" on the state of the iomgr.
* For instance, closures created during a shutdown would have this field set
* to false. */
int success;
/**< Internal. Do not touch */
struct grpc_closure *next;
};
/** Initializes \a closure with \a cb and \a cb_arg. */
void grpc_closure_init(grpc_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg);
#define GRPC_CLOSURE_LIST_INIT \
{ NULL, NULL }
void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure,
int success);
void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);
int grpc_closure_list_empty(grpc_closure_list list);
#endif /* GRPC_INTERNAL_CORE_IOMGR_CLOSURE_H */

@ -33,31 +33,35 @@
#include "src/core/iomgr/endpoint.h"
grpc_endpoint_op_status grpc_endpoint_read(grpc_endpoint *ep,
gpr_slice_buffer *slices,
grpc_iomgr_closure *cb) {
return ep->vtable->read(ep, slices, cb);
void grpc_endpoint_read(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
gpr_slice_buffer* slices, grpc_closure* cb) {
ep->vtable->read(exec_ctx, ep, slices, cb);
}
grpc_endpoint_op_status grpc_endpoint_write(grpc_endpoint *ep,
gpr_slice_buffer *slices,
grpc_iomgr_closure *cb) {
return ep->vtable->write(ep, slices, cb);
void grpc_endpoint_write(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
gpr_slice_buffer* slices, grpc_closure* cb) {
ep->vtable->write(exec_ctx, ep, slices, cb);
}
void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
ep->vtable->add_to_pollset(ep, pollset);
void grpc_endpoint_add_to_pollset(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep,
grpc_pollset* pollset) {
ep->vtable->add_to_pollset(exec_ctx, ep, pollset);
}
void grpc_endpoint_add_to_pollset_set(grpc_endpoint *ep,
grpc_pollset_set *pollset_set) {
ep->vtable->add_to_pollset_set(ep, pollset_set);
void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx* exec_ctx,
grpc_endpoint* ep,
grpc_pollset_set* pollset_set) {
ep->vtable->add_to_pollset_set(exec_ctx, ep, pollset_set);
}
void grpc_endpoint_shutdown(grpc_endpoint *ep) { ep->vtable->shutdown(ep); }
void grpc_endpoint_shutdown(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
ep->vtable->shutdown(exec_ctx, ep);
}
void grpc_endpoint_destroy(grpc_endpoint *ep) { ep->vtable->destroy(ep); }
void grpc_endpoint_destroy(grpc_exec_ctx* exec_ctx, grpc_endpoint* ep) {
ep->vtable->destroy(exec_ctx, ep);
}
char *grpc_endpoint_get_peer(grpc_endpoint *ep) {
char* grpc_endpoint_get_peer(grpc_endpoint* ep) {
return ep->vtable->get_peer(ep);
}

@ -46,21 +46,17 @@
typedef struct grpc_endpoint grpc_endpoint;
typedef struct grpc_endpoint_vtable grpc_endpoint_vtable;
typedef enum grpc_endpoint_op_status {
GRPC_ENDPOINT_DONE, /* completed immediately, cb won't be called */
GRPC_ENDPOINT_PENDING, /* cb will be called when completed */
GRPC_ENDPOINT_ERROR /* write errored out, cb won't be called */
} grpc_endpoint_op_status;
struct grpc_endpoint_vtable {
grpc_endpoint_op_status (*read)(grpc_endpoint *ep, gpr_slice_buffer *slices,
grpc_iomgr_closure *cb);
grpc_endpoint_op_status (*write)(grpc_endpoint *ep, gpr_slice_buffer *slices,
grpc_iomgr_closure *cb);
void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset);
void (*add_to_pollset_set)(grpc_endpoint *ep, grpc_pollset_set *pollset);
void (*shutdown)(grpc_endpoint *ep);
void (*destroy)(grpc_endpoint *ep);
void (*read)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *slices, grpc_closure *cb);
void (*write)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *slices, grpc_closure *cb);
void (*add_to_pollset)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset *pollset);
void (*add_to_pollset_set)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset_set *pollset);
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
char *(*get_peer)(grpc_endpoint *ep);
};
@ -68,9 +64,8 @@ struct grpc_endpoint_vtable {
Callback success indicates that the endpoint can accept more reads, failure
indicates the endpoint is closed.
Valid slices may be placed into \a slices even on callback success == 0. */
grpc_endpoint_op_status grpc_endpoint_read(
grpc_endpoint *ep, gpr_slice_buffer *slices,
grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT;
void grpc_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *slices, grpc_closure *cb);
char *grpc_endpoint_get_peer(grpc_endpoint *ep);
@ -84,19 +79,20 @@ char *grpc_endpoint_get_peer(grpc_endpoint *ep);
No guarantee is made to the content of slices after a write EXCEPT that
it is a valid slice buffer.
*/
grpc_endpoint_op_status grpc_endpoint_write(
grpc_endpoint *ep, gpr_slice_buffer *slices,
grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT;
void grpc_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *slices, grpc_closure *cb);
/* Causes any pending read/write callbacks to run immediately with
success==0 */
void grpc_endpoint_shutdown(grpc_endpoint *ep);
void grpc_endpoint_destroy(grpc_endpoint *ep);
void grpc_endpoint_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
void grpc_endpoint_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep);
/* Add an endpoint to a pollset, so that when the pollset is polled, events from
this endpoint are considered */
void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset);
void grpc_endpoint_add_to_pollset_set(grpc_endpoint *ep,
void grpc_endpoint_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset *pollset);
void grpc_endpoint_add_to_pollset_set(grpc_exec_ctx *exec_ctx,
grpc_endpoint *ep,
grpc_pollset_set *pollset_set);
struct grpc_endpoint {

@ -0,0 +1,62 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/iomgr/exec_ctx.h"
#include <grpc/support/log.h>
void grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
while (!grpc_closure_list_empty(exec_ctx->closure_list)) {
grpc_closure *c = exec_ctx->closure_list.head;
exec_ctx->closure_list.head = exec_ctx->closure_list.tail = NULL;
while (c != NULL) {
grpc_closure *next = c->next;
c->cb(exec_ctx, c->cb_arg, c->success);
c = next;
}
}
}
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {
grpc_exec_ctx_flush(exec_ctx);
}
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
int success) {
grpc_closure_list_add(&exec_ctx->closure_list, closure, success);
}
void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list) {
grpc_closure_list_move(list, &exec_ctx->closure_list);
}

@ -0,0 +1,77 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_CORE_IOMGR_EXEC_CTX_H
#define GRPC_INTERNAL_CORE_IOMGR_EXEC_CTX_H
#include "src/core/iomgr/closure.h"
/** Execution context.
* A bag of data that collects information along a callstack.
* Generally created at public API entry points, and passed down as
* pointer to child functions that manipulate it.
*
* Specific responsibilities (this may grow in the future):
* - track a list of work that needs to be delayed until the top of the
* call stack (this provides a convenient mechanism to run callbacks
* without worrying about locking issues)
*
* CONVENTIONS:
* Instance of this must ALWAYS be constructed on the stack, never
* heap allocated. Instances and pointers to them must always be called
* exec_ctx. Instances are always passed as the first argument
* to a function that takes it, and always as a pointer (grpc_exec_ctx
* is never copied).
*/
struct grpc_exec_ctx {
grpc_closure_list closure_list;
};
#define GRPC_EXEC_CTX_INIT \
{ GRPC_CLOSURE_LIST_INIT }
/** Flush any work that has been enqueued onto this grpc_exec_ctx.
* Caller must guarantee that no interfering locks are held. */
void grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx);
/** Finish any pending work for a grpc_exec_ctx. Must be called before
* the instance is destroyed, or work may be lost. */
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx);
/** Add a closure to be executed at the next flush/finish point */
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
int success);
/** Add a list of closures to be executed at the next flush/finish point.
* Leaves \a list empty. */
void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list);
#endif

@ -150,6 +150,8 @@ static void unref_by(grpc_fd *fd, int n) {
void grpc_fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); }
void grpc_fd_global_shutdown(void) {
gpr_mu_lock(&fd_freelist_mu);
gpr_mu_unlock(&fd_freelist_mu);
while (fd_freelist != NULL) {
grpc_fd *fd = fd_freelist;
fd_freelist = fd_freelist->freelist_next;
@ -161,6 +163,9 @@ void grpc_fd_global_shutdown(void) {
grpc_fd *grpc_fd_create(int fd, const char *name) {
grpc_fd *r = alloc_fd(fd);
grpc_iomgr_register_object(&r->iomgr_object, name);
#ifdef GRPC_FD_REF_COUNT_DEBUG
gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, r, name);
#endif
return r;
}
@ -209,7 +214,7 @@ static int has_watchers(grpc_fd *fd) {
fd->inactive_watcher_root.next != &fd->inactive_watcher_root;
}
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
const char *reason) {
fd->on_done_closure = on_done;
shutdown(fd->fd, SHUT_RDWR);
@ -218,9 +223,7 @@ void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
if (!has_watchers(fd)) {
fd->closed = 1;
close(fd->fd);
if (fd->on_done_closure) {
grpc_iomgr_add_callback(fd->on_done_closure);
}
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
} else {
wake_all_watchers_locked(fd);
}
@ -244,25 +247,8 @@ void grpc_fd_ref(grpc_fd *fd) { ref_by(fd, 2); }
void grpc_fd_unref(grpc_fd *fd) { unref_by(fd, 2); }
#endif
static void process_callback(grpc_iomgr_closure *closure, int success,
int allow_synchronous_callback) {
if (allow_synchronous_callback) {
closure->cb(closure->cb_arg, success);
} else {
grpc_iomgr_add_delayed_callback(closure, success);
}
}
static void process_callbacks(grpc_iomgr_closure *callbacks, size_t n,
int success, int allow_synchronous_callback) {
size_t i;
for (i = 0; i < n; i++) {
process_callback(callbacks + i, success, allow_synchronous_callback);
}
}
static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure,
int allow_synchronous_callback) {
static void notify_on(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *st,
grpc_closure *closure) {
switch (gpr_atm_acq_load(st)) {
case NOT_READY:
/* There is no race if the descriptor is already ready, so we skip
@ -284,8 +270,8 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure,
case READY:
GPR_ASSERT(gpr_atm_no_barrier_load(st) == READY);
gpr_atm_rel_store(st, NOT_READY);
process_callback(closure, !gpr_atm_acq_load(&fd->shutdown),
allow_synchronous_callback);
grpc_exec_ctx_enqueue(exec_ctx, closure,
!gpr_atm_acq_load(&fd->shutdown));
return;
default: /* WAITING */
/* upcallptr was set to a different closure. This is an error! */
@ -298,8 +284,8 @@ static void notify_on(grpc_fd *fd, gpr_atm *st, grpc_iomgr_closure *closure,
abort();
}
static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure **callbacks,
size_t *ncallbacks) {
static void set_ready_locked(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
gpr_atm *st) {
gpr_intptr state = gpr_atm_acq_load(st);
switch (state) {
@ -318,49 +304,38 @@ static void set_ready_locked(gpr_atm *st, grpc_iomgr_closure **callbacks,
default: /* waiting */
GPR_ASSERT(gpr_atm_no_barrier_load(st) != READY &&
gpr_atm_no_barrier_load(st) != NOT_READY);
callbacks[(*ncallbacks)++] = (grpc_iomgr_closure *)state;
grpc_exec_ctx_enqueue(exec_ctx, (grpc_closure *)state,
!gpr_atm_acq_load(&fd->shutdown));
gpr_atm_rel_store(st, NOT_READY);
return;
}
}
static void set_ready(grpc_fd *fd, gpr_atm *st,
int allow_synchronous_callback) {
static void set_ready(grpc_exec_ctx *exec_ctx, grpc_fd *fd, gpr_atm *st) {
/* only one set_ready can be active at once (but there may be a racing
notify_on) */
int success;
grpc_iomgr_closure *closure;
size_t ncb = 0;
gpr_mu_lock(&fd->set_state_mu);
set_ready_locked(st, &closure, &ncb);
set_ready_locked(exec_ctx, fd, st);
gpr_mu_unlock(&fd->set_state_mu);
success = !gpr_atm_acq_load(&fd->shutdown);
GPR_ASSERT(ncb <= 1);
if (ncb > 0) {
process_callbacks(closure, ncb, success, allow_synchronous_callback);
}
}
void grpc_fd_shutdown(grpc_fd *fd) {
size_t ncb = 0;
void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
gpr_mu_lock(&fd->set_state_mu);
GPR_ASSERT(!gpr_atm_no_barrier_load(&fd->shutdown));
gpr_atm_rel_store(&fd->shutdown, 1);
set_ready_locked(&fd->readst, &fd->shutdown_closures[0], &ncb);
set_ready_locked(&fd->writest, &fd->shutdown_closures[0], &ncb);
set_ready_locked(exec_ctx, fd, &fd->readst);
set_ready_locked(exec_ctx, fd, &fd->writest);
gpr_mu_unlock(&fd->set_state_mu);
GPR_ASSERT(ncb <= 2);
process_callbacks(fd->shutdown_closures[0], ncb, 0 /* GPR_FALSE */,
0 /* GPR_FALSE */);
}
void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure) {
notify_on(fd, &fd->readst, closure, 0);
void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure) {
notify_on(exec_ctx, fd, &fd->readst, closure);
}
void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_closure *closure) {
notify_on(fd, &fd->writest, closure, 0);
void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure) {
notify_on(exec_ctx, fd, &fd->writest, closure);
}
gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
@ -406,7 +381,8 @@ gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
return mask;
}
void grpc_fd_end_poll(grpc_fd_watcher *watcher, int got_read, int got_write) {
void grpc_fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *watcher,
int got_read, int got_write) {
int was_polling = 0;
int kick = 0;
grpc_fd *fd = watcher->fd;
@ -439,21 +415,19 @@ void grpc_fd_end_poll(grpc_fd_watcher *watcher, int got_read, int got_write) {
if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
fd->closed = 1;
close(fd->fd);
if (fd->on_done_closure != NULL) {
grpc_iomgr_add_callback(fd->on_done_closure);
}
grpc_exec_ctx_enqueue(exec_ctx, fd->on_done_closure, 1);
}
gpr_mu_unlock(&fd->watcher_mu);
GRPC_FD_UNREF(fd, "poll");
}
void grpc_fd_become_readable(grpc_fd *fd, int allow_synchronous_callback) {
set_ready(fd, &fd->readst, allow_synchronous_callback);
void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
set_ready(exec_ctx, fd, &fd->readst);
}
void grpc_fd_become_writable(grpc_fd *fd, int allow_synchronous_callback) {
set_ready(fd, &fd->writest, allow_synchronous_callback);
void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) {
set_ready(exec_ctx, fd, &fd->writest);
}
#endif

@ -52,8 +52,8 @@ typedef struct grpc_fd_watcher {
struct grpc_fd {
int fd;
/* refst format:
bit0: 1=active/0=orphaned
bit1-n: refcount
bit0: 1=active/0=orphaned
bit1-n: refcount
meaning that mostly we ref by two to avoid altering the orphaned bit,
and just unref by 1 when we're ready to flag the object as orphaned */
gpr_atm refst;
@ -94,8 +94,8 @@ struct grpc_fd {
struct grpc_fd *freelist_next;
grpc_iomgr_closure *on_done_closure;
grpc_iomgr_closure *shutdown_closures[2];
grpc_closure *on_done_closure;
grpc_closure *shutdown_closures[2];
grpc_iomgr_object iomgr_object;
};
@ -111,7 +111,7 @@ grpc_fd *grpc_fd_create(int fd, const char *name);
Requires: *fd initialized; no outstanding notify_on_read or
notify_on_write.
MUST NOT be called with a pollset lock taken */
void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
void grpc_fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_closure *on_done,
const char *reason);
/* Begin polling on an fd.
@ -130,13 +130,14 @@ gpr_uint32 grpc_fd_begin_poll(grpc_fd *fd, grpc_pollset *pollset,
grpc_fd_watcher *rec);
/* Complete polling previously started with grpc_fd_begin_poll
MUST NOT be called with a pollset lock taken */
void grpc_fd_end_poll(grpc_fd_watcher *rec, int got_read, int got_write);
void grpc_fd_end_poll(grpc_exec_ctx *exec_ctx, grpc_fd_watcher *rec,
int got_read, int got_write);
/* Return 1 if this fd is orphaned, 0 otherwise */
int grpc_fd_is_orphaned(grpc_fd *fd);
/* Cause any current callbacks to error out with GRPC_CALLBACK_CANCELLED. */
void grpc_fd_shutdown(grpc_fd *fd);
void grpc_fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
/* Register read interest, causing read_cb to be called once when fd becomes
readable, on deadline specified by deadline, or on shutdown triggered by
@ -151,17 +152,19 @@ void grpc_fd_shutdown(grpc_fd *fd);
underlying platform. This means that users must drain fd in read_cb before
calling notify_on_read again. Users are also expected to handle spurious
events, i.e read_cb is called while nothing can be readable from fd */
void grpc_fd_notify_on_read(grpc_fd *fd, grpc_iomgr_closure *closure);
void grpc_fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure);
/* Exactly the same semantics as above, except based on writable events. */
void grpc_fd_notify_on_write(grpc_fd *fd, grpc_iomgr_closure *closure);
void grpc_fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
grpc_closure *closure);
/* Notification from the poller to an fd that it has become readable or
writable.
If allow_synchronous_callback is 1, allow running the fd callback inline
in this callstack, otherwise register an asynchronous callback and return */
void grpc_fd_become_readable(grpc_fd *fd, int allow_synchronous_callback);
void grpc_fd_become_writable(grpc_fd *fd, int allow_synchronous_callback);
void grpc_fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
void grpc_fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd);
/* Reference counting for fds */
#ifdef GRPC_FD_REF_COUNT_DEBUG

@ -56,7 +56,7 @@ static gpr_atm g_custom_events = 0;
static HANDLE g_iocp;
static void do_iocp_work() {
static void do_iocp_work(grpc_exec_ctx *exec_ctx) {
BOOL success;
DWORD bytes = 0;
DWORD flags = 0;
@ -64,8 +64,7 @@ static void do_iocp_work() {
LPOVERLAPPED overlapped;
grpc_winsocket *socket;
grpc_winsocket_callback_info *info;
void (*f)(void *, int) = NULL;
void *opaque = NULL;
grpc_closure *closure = NULL;
success = GetQueuedCompletionStatus(g_iocp, &bytes, &completion_key,
&overlapped, INFINITE);
/* success = 0 and overlapped = NULL means the deadline got attained.
@ -98,22 +97,27 @@ static void do_iocp_work() {
GPR_ASSERT(overlapped == &info->overlapped);
GPR_ASSERT(!info->has_pending_iocp);
gpr_mu_lock(&socket->state_mu);
if (info->cb) {
f = info->cb;
opaque = info->opaque;
info->cb = NULL;
if (info->closure) {
closure = info->closure;
info->closure = NULL;
} else {
info->has_pending_iocp = 1;
}
gpr_mu_unlock(&socket->state_mu);
if (f) f(opaque, 1);
if (closure) {
closure->cb(exec_ctx, closure->cb_arg, 1);
}
}
static void iocp_loop(void *p) {
while (gpr_atm_acq_load(&g_custom_events) ||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
while (gpr_atm_acq_load(&g_custom_events) ||
!gpr_event_get(&g_shutdown_iocp)) {
do_iocp_work();
do_iocp_work(&exec_ctx);
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
gpr_event_set(&g_iocp_done, (void *)1);
}
@ -168,31 +172,31 @@ void grpc_iocp_add_socket(grpc_winsocket *socket) {
-) The IOCP already completed in the background, and we need to call
the callback now.
-) The IOCP hasn't completed yet, and we're queuing it for later. */
static void socket_notify_on_iocp(grpc_winsocket *socket,
void (*cb)(void *, int), void *opaque,
static void socket_notify_on_iocp(grpc_exec_ctx *exec_ctx,
grpc_winsocket *socket, grpc_closure *closure,
grpc_winsocket_callback_info *info) {
int run_now = 0;
GPR_ASSERT(!info->cb);
GPR_ASSERT(info->closure == NULL);
gpr_mu_lock(&socket->state_mu);
if (info->has_pending_iocp) {
run_now = 1;
info->has_pending_iocp = 0;
grpc_exec_ctx_enqueue(exec_ctx, closure, 1);
} else {
info->cb = cb;
info->opaque = opaque;
info->closure = closure;
}
gpr_mu_unlock(&socket->state_mu);
if (run_now) cb(opaque, 1);
}
void grpc_socket_notify_on_write(grpc_winsocket *socket,
void (*cb)(void *, int), void *opaque) {
socket_notify_on_iocp(socket, cb, opaque, &socket->write_info);
void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
grpc_winsocket *socket,
grpc_closure *closure) {
socket_notify_on_iocp(exec_ctx, socket, closure, &socket->write_info);
}
void grpc_socket_notify_on_read(grpc_winsocket *socket, void (*cb)(void *, int),
void *opaque) {
socket_notify_on_iocp(socket, cb, opaque, &socket->read_info);
void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_winsocket *socket,
grpc_closure *closure) {
socket_notify_on_iocp(exec_ctx, socket, closure, &socket->read_info);
}
#endif /* GPR_WINSOCK_SOCKET */

@ -43,10 +43,12 @@ void grpc_iocp_kick(void);
void grpc_iocp_shutdown(void);
void grpc_iocp_add_socket(grpc_winsocket *);
void grpc_socket_notify_on_write(grpc_winsocket *,
void (*cb)(void *, int success), void *opaque);
void grpc_socket_notify_on_write(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_closure *closure);
void grpc_socket_notify_on_read(grpc_winsocket *,
void (*cb)(void *, int success), void *opaque);
void grpc_socket_notify_on_read(grpc_exec_ctx *exec_ctx,
grpc_winsocket *winsocket,
grpc_closure *closure);
#endif /* GRPC_INTERNAL_CORE_IOMGR_IOCP_WINDOWS_H */

@ -48,39 +48,9 @@
static gpr_mu g_mu;
static gpr_cv g_rcv;
static grpc_iomgr_closure *g_cbs_head = NULL;
static grpc_iomgr_closure *g_cbs_tail = NULL;
static int g_shutdown;
static gpr_event g_background_callback_executor_done;
static grpc_iomgr_object g_root_object;
/* Execute followup callbacks continuously.
Other threads may check in and help during pollset_work() */
static void background_callback_executor(void *ignored) {
gpr_mu_lock(&g_mu);
while (!g_shutdown) {
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
gpr_timespec short_deadline = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(100, GPR_TIMESPAN));
if (g_cbs_head) {
grpc_iomgr_closure *closure = g_cbs_head;
g_cbs_head = closure->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
closure->cb(closure->cb_arg, closure->success);
gpr_mu_lock(&g_mu);
} else if (grpc_alarm_check(&g_mu, gpr_now(GPR_CLOCK_MONOTONIC),
&deadline)) {
} else {
gpr_mu_unlock(&g_mu);
gpr_sleep_until(gpr_time_min(short_deadline, deadline));
gpr_mu_lock(&g_mu);
}
}
gpr_mu_unlock(&g_mu);
gpr_event_set(&g_background_callback_executor_done, (void *)1);
}
void grpc_kick_poller(void) {
/* Empty. The background callback executor polls periodically. The activity
* the kicker is trying to draw the executor's attention to will be picked up
@ -89,7 +59,6 @@ void grpc_kick_poller(void) {
}
void grpc_iomgr_init(void) {
gpr_thd_id id;
g_shutdown = 0;
gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv);
@ -97,8 +66,6 @@ void grpc_iomgr_init(void) {
g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = "root";
grpc_iomgr_platform_init();
gpr_event_init(&g_background_callback_executor_done);
gpr_thd_new(&id, background_callback_executor, NULL, NULL);
}
static size_t count_objects(void) {
@ -118,76 +85,55 @@ static void dump_objects(const char *kind) {
}
void grpc_iomgr_shutdown(void) {
grpc_iomgr_closure *closure;
gpr_timespec shutdown_deadline = gpr_time_add(
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN));
gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_mu_lock(&g_mu);
g_shutdown = 1;
while (g_cbs_head != NULL || g_root_object.next != &g_root_object) {
while (g_root_object.next != &g_root_object) {
if (gpr_time_cmp(
gpr_time_sub(gpr_now(GPR_CLOCK_REALTIME), last_warning_time),
gpr_time_from_seconds(1, GPR_TIMESPAN)) >= 0) {
if (g_cbs_head != NULL && g_root_object.next != &g_root_object) {
gpr_log(GPR_DEBUG,
"Waiting for %d iomgr objects to be destroyed and executing "
"final callbacks",
count_objects());
} else if (g_cbs_head != NULL) {
gpr_log(GPR_DEBUG, "Executing final iomgr callbacks");
} else {
if (g_root_object.next != &g_root_object) {
gpr_log(GPR_DEBUG, "Waiting for %d iomgr objects to be destroyed",
count_objects());
}
last_warning_time = gpr_now(GPR_CLOCK_REALTIME);
}
if (g_cbs_head) {
do {
closure = g_cbs_head;
g_cbs_head = closure->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
closure->cb(closure->cb_arg, 0);
gpr_mu_lock(&g_mu);
} while (g_cbs_head);
continue;
}
if (grpc_alarm_check(&g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL)) {
if (grpc_alarm_check(&exec_ctx, gpr_inf_future(GPR_CLOCK_MONOTONIC),
NULL)) {
gpr_mu_unlock(&g_mu);
grpc_exec_ctx_flush(&exec_ctx);
gpr_mu_lock(&g_mu);
continue;
}
if (g_root_object.next != &g_root_object) {
int timeout = 0;
while (g_cbs_head == NULL) {
gpr_timespec short_deadline = gpr_time_add(
gpr_timespec short_deadline = gpr_time_add(
gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN));
if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) {
if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
timeout = 1;
break;
if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline)) {
if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) {
if (g_root_object.next != &g_root_object) {
gpr_log(GPR_DEBUG,
"Failed to free %d iomgr objects before shutdown deadline: "
"memory leaks are likely",
count_objects());
dump_objects("LEAKED");
}
break;
}
}
if (timeout) {
gpr_log(GPR_DEBUG,
"Failed to free %d iomgr objects before shutdown deadline: "
"memory leaks are likely",
count_objects());
dump_objects("LEAKED");
break;
}
}
}
gpr_mu_unlock(&g_mu);
memset(&g_root_object, 0, sizeof(g_root_object));
grpc_alarm_list_shutdown(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
grpc_kick_poller();
gpr_event_wait(&g_background_callback_executor_done,
gpr_inf_future(GPR_CLOCK_REALTIME));
grpc_alarm_list_shutdown();
/* ensure all threads have left g_mu */
gpr_mu_lock(&g_mu);
gpr_mu_unlock(&g_mu);
grpc_iomgr_platform_shutdown();
gpr_mu_destroy(&g_mu);
@ -211,74 +157,3 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
gpr_mu_unlock(&g_mu);
gpr_free(obj->name);
}
void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg) {
closure->cb = cb;
closure->cb_arg = cb_arg;
closure->next = NULL;
}
static void assert_not_scheduled_locked(grpc_iomgr_closure *closure) {
#ifndef NDEBUG
grpc_iomgr_closure *c;
for (c = g_cbs_head; c; c = c->next) {
GPR_ASSERT(c != closure);
}
#endif
}
void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *closure, int success) {
closure->success = success;
GPR_ASSERT(closure->cb);
gpr_mu_lock(&g_mu);
assert_not_scheduled_locked(closure);
closure->next = NULL;
if (!g_cbs_tail) {
g_cbs_head = g_cbs_tail = closure;
} else {
g_cbs_tail->next = closure;
g_cbs_tail = closure;
}
if (g_shutdown) {
gpr_cv_signal(&g_rcv);
}
gpr_mu_unlock(&g_mu);
}
void grpc_iomgr_add_callback(grpc_iomgr_closure *closure) {
grpc_iomgr_add_delayed_callback(closure, 1 /* GPR_TRUE */);
}
int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success) {
int n = 0;
gpr_mu *retake_mu = NULL;
grpc_iomgr_closure *closure;
for (;;) {
/* check for new work */
if (!gpr_mu_trylock(&g_mu)) {
break;
}
closure = g_cbs_head;
if (!closure) {
gpr_mu_unlock(&g_mu);
break;
}
g_cbs_head = closure->next;
if (!g_cbs_head) g_cbs_tail = NULL;
gpr_mu_unlock(&g_mu);
/* if we have a mutex to drop, do so before executing work */
if (drop_mu) {
gpr_mu_unlock(drop_mu);
retake_mu = drop_mu;
drop_mu = NULL;
}
closure->cb(closure->cb_arg, success && closure->success);
n++;
}
if (retake_mu) {
gpr_mu_lock(retake_mu);
}
return n;
}

@ -34,47 +34,10 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_H
#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_H
/** gRPC Callback definition.
*
* \param arg Arbitrary input.
* \param success An indication on the state of the iomgr. On false, cleanup
* actions should be taken (eg, shutdown). */
typedef void (*grpc_iomgr_cb_func)(void *arg, int success);
/** A closure over a grpc_iomgr_cb_func. */
typedef struct grpc_iomgr_closure {
/** Bound callback. */
grpc_iomgr_cb_func cb;
/** Arguments to be passed to "cb". */
void *cb_arg;
/** Internal. A boolean indication to "cb" on the state of the iomgr.
* For instance, closures created during a shutdown would have this field set
* to false. */
int success;
/**< Internal. Do not touch */
struct grpc_iomgr_closure *next;
} grpc_iomgr_closure;
/** Initializes \a closure with \a cb and \a cb_arg. */
void grpc_iomgr_closure_init(grpc_iomgr_closure *closure, grpc_iomgr_cb_func cb,
void *cb_arg);
/** Initializes the iomgr. */
void grpc_iomgr_init(void);
/** Signals the intention to shutdown the iomgr. */
void grpc_iomgr_shutdown(void);
/** Registers a closure to be invoked at some point in the future.
*
* Can be called from within a callback or from anywhere else */
void grpc_iomgr_add_callback(grpc_iomgr_closure *closure);
/** As per grpc_iomgr_add_callback, with the ability to set the success
argument. */
void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success);
#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_H */

@ -43,9 +43,6 @@ typedef struct grpc_iomgr_object {
struct grpc_iomgr_object *prev;
} grpc_iomgr_object;
int grpc_maybe_call_delayed_callbacks(gpr_mu *drop_mu, int success);
void grpc_iomgr_add_delayed_callback(grpc_iomgr_closure *iocb, int success);
void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name);
void grpc_iomgr_unregister_object(grpc_iomgr_object *obj);

@ -55,9 +55,8 @@
#endif
void grpc_pollset_init(grpc_pollset *pollset);
void grpc_pollset_shutdown(grpc_pollset *pollset,
void (*shutdown_done)(void *arg),
void *shutdown_done_arg);
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure);
void grpc_pollset_destroy(grpc_pollset *pollset);
/* Do some work on a pollset.
@ -74,9 +73,13 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
grpc_pollset_work, and it is guaranteed that GRPC_POLLSET_MU(pollset) will
not be released by grpc_pollset_work AFTER worker has been destroyed.
Tries not to block past deadline. */
void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec now, gpr_timespec deadline);
Tries not to block past deadline.
May call grpc_closure_list_run on grpc_closure_list, without holding the
pollset
lock */
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker *worker, gpr_timespec now,
gpr_timespec deadline);
/* Break one polling thread out of polling work for this pollset.
If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers.

@ -53,7 +53,7 @@ typedef struct wakeup_fd_hdl {
typedef struct {
grpc_pollset *pollset;
grpc_fd *fd;
grpc_iomgr_closure closure;
grpc_closure closure;
} delayed_add;
typedef struct {
@ -61,7 +61,8 @@ typedef struct {
wakeup_fd_hdl *free_wakeup_fds;
} pollset_hdr;
static void finally_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
static void finally_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd) {
pollset_hdr *h = pollset->data.ptr;
struct epoll_event ev;
int err;
@ -83,15 +84,15 @@ static void finally_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
}
}
}
grpc_fd_end_poll(&watcher, 0, 0);
grpc_fd_end_poll(exec_ctx, &watcher, 0, 0);
}
static void perform_delayed_add(void *arg, int iomgr_status) {
static void perform_delayed_add(grpc_exec_ctx *exec_ctx, void *arg,
int iomgr_status) {
delayed_add *da = arg;
int do_shutdown_cb = 0;
if (!grpc_fd_is_orphaned(da->fd)) {
finally_add_fd(da->pollset, da->fd);
finally_add_fd(exec_ctx, da->pollset, da->fd);
}
gpr_mu_lock(&da->pollset->mu);
@ -100,38 +101,36 @@ static void perform_delayed_add(void *arg, int iomgr_status) {
/* We don't care about this pollset anymore. */
if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) {
da->pollset->called_shutdown = 1;
do_shutdown_cb = 1;
grpc_exec_ctx_enqueue(exec_ctx, da->pollset->shutdown_done, 1);
}
}
gpr_mu_unlock(&da->pollset->mu);
GRPC_FD_UNREF(da->fd, "delayed_add");
if (do_shutdown_cb) {
da->pollset->shutdown_done_cb(da->pollset->shutdown_done_arg);
}
gpr_free(da);
}
static void multipoll_with_epoll_pollset_add_fd(grpc_pollset *pollset,
static void multipoll_with_epoll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_fd *fd,
int and_unlock_pollset) {
if (and_unlock_pollset) {
gpr_mu_unlock(&pollset->mu);
finally_add_fd(pollset, fd);
finally_add_fd(exec_ctx, pollset, fd);
} else {
delayed_add *da = gpr_malloc(sizeof(*da));
da->pollset = pollset;
da->fd = fd;
GRPC_FD_REF(fd, "delayed_add");
grpc_iomgr_closure_init(&da->closure, perform_delayed_add, da);
grpc_closure_init(&da->closure, perform_delayed_add, da);
pollset->in_flight_cbs++;
grpc_iomgr_add_callback(&da->closure);
grpc_exec_ctx_enqueue(exec_ctx, &da->closure, 1);
}
}
static void multipoll_with_epoll_pollset_del_fd(grpc_pollset *pollset,
static void multipoll_with_epoll_pollset_del_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_fd *fd,
int and_unlock_pollset) {
pollset_hdr *h = pollset->data.ptr;
@ -153,9 +152,9 @@ static void multipoll_with_epoll_pollset_del_fd(grpc_pollset *pollset,
/* TODO(klempner): We probably want to turn this down a bit */
#define GRPC_EPOLL_MAX_EVENTS 1000
static void multipoll_with_epoll_pollset_maybe_work(
grpc_pollset *pollset, grpc_pollset_worker *worker, gpr_timespec deadline,
gpr_timespec now, int allow_synchronous_callback) {
static void multipoll_with_epoll_pollset_maybe_work_and_unlock(
grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now) {
struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS];
int ep_rv;
int poll_rv;
@ -209,18 +208,16 @@ static void multipoll_with_epoll_pollset_maybe_work(
int read = ep_ev[i].events & (EPOLLIN | EPOLLPRI);
int write = ep_ev[i].events & EPOLLOUT;
if (read || cancel) {
grpc_fd_become_readable(fd, allow_synchronous_callback);
grpc_fd_become_readable(exec_ctx, fd);
}
if (write || cancel) {
grpc_fd_become_writable(fd, allow_synchronous_callback);
grpc_fd_become_writable(exec_ctx, fd);
}
}
}
} while (ep_rv == GRPC_EPOLL_MAX_EVENTS);
}
}
gpr_mu_lock(&pollset->mu);
}
static void multipoll_with_epoll_pollset_finish_shutdown(
@ -234,11 +231,12 @@ static void multipoll_with_epoll_pollset_destroy(grpc_pollset *pollset) {
static const grpc_pollset_vtable multipoll_with_epoll_pollset = {
multipoll_with_epoll_pollset_add_fd, multipoll_with_epoll_pollset_del_fd,
multipoll_with_epoll_pollset_maybe_work,
multipoll_with_epoll_pollset_maybe_work_and_unlock,
multipoll_with_epoll_pollset_finish_shutdown,
multipoll_with_epoll_pollset_destroy};
static void epoll_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
static void epoll_become_multipoller(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset, grpc_fd **fds,
size_t nfds) {
size_t i;
pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr));
@ -252,7 +250,7 @@ static void epoll_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
abort();
}
for (i = 0; i < nfds; i++) {
multipoll_with_epoll_pollset_add_fd(pollset, fds[i], 0);
multipoll_with_epoll_pollset_add_fd(exec_ctx, pollset, fds[i], 0);
}
}

@ -59,7 +59,8 @@ typedef struct {
grpc_fd **dels;
} pollset_hdr;
static void multipoll_with_poll_pollset_add_fd(grpc_pollset *pollset,
static void multipoll_with_poll_pollset_add_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_fd *fd,
int and_unlock_pollset) {
size_t i;
@ -80,7 +81,8 @@ exit:
}
}
static void multipoll_with_poll_pollset_del_fd(grpc_pollset *pollset,
static void multipoll_with_poll_pollset_del_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_fd *fd,
int and_unlock_pollset) {
/* will get removed next poll cycle */
@ -96,9 +98,9 @@ static void multipoll_with_poll_pollset_del_fd(grpc_pollset *pollset,
}
}
static void multipoll_with_poll_pollset_maybe_work(
grpc_pollset *pollset, grpc_pollset_worker *worker, gpr_timespec deadline,
gpr_timespec now, int allow_synchronous_callback) {
static void multipoll_with_poll_pollset_maybe_work_and_unlock(
grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now) {
int timeout;
int r;
size_t i, j, fd_count;
@ -148,7 +150,7 @@ static void multipoll_with_poll_pollset_maybe_work(
r = grpc_poll_function(pfds, pfd_count, timeout);
for (i = 1; i < pfd_count; i++) {
grpc_fd_end_poll(&watchers[i], pfds[i].revents & POLLIN,
grpc_fd_end_poll(exec_ctx, &watchers[i], pfds[i].revents & POLLIN,
pfds[i].revents & POLLOUT);
}
@ -167,18 +169,16 @@ static void multipoll_with_poll_pollset_maybe_work(
continue;
}
if (pfds[i].revents & (POLLIN | POLLHUP | POLLERR)) {
grpc_fd_become_readable(watchers[i].fd, allow_synchronous_callback);
grpc_fd_become_readable(exec_ctx, watchers[i].fd);
}
if (pfds[i].revents & (POLLOUT | POLLHUP | POLLERR)) {
grpc_fd_become_writable(watchers[i].fd, allow_synchronous_callback);
grpc_fd_become_writable(exec_ctx, watchers[i].fd);
}
}
}
gpr_free(pfds);
gpr_free(watchers);
gpr_mu_lock(&pollset->mu);
}
static void multipoll_with_poll_pollset_finish_shutdown(grpc_pollset *pollset) {
@ -204,11 +204,12 @@ static void multipoll_with_poll_pollset_destroy(grpc_pollset *pollset) {
static const grpc_pollset_vtable multipoll_with_poll_pollset = {
multipoll_with_poll_pollset_add_fd, multipoll_with_poll_pollset_del_fd,
multipoll_with_poll_pollset_maybe_work,
multipoll_with_poll_pollset_maybe_work_and_unlock,
multipoll_with_poll_pollset_finish_shutdown,
multipoll_with_poll_pollset_destroy};
void grpc_poll_become_multipoller(grpc_pollset *pollset, grpc_fd **fds,
void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset, grpc_fd **fds,
size_t nfds) {
size_t i;
pollset_hdr *h = gpr_malloc(sizeof(pollset_hdr));

@ -136,12 +136,14 @@ void grpc_pollset_init(grpc_pollset *pollset) {
pollset->in_flight_cbs = 0;
pollset->shutting_down = 0;
pollset->called_shutdown = 0;
pollset->idle_jobs.head = pollset->idle_jobs.tail = NULL;
become_basic_pollset(pollset, NULL);
}
void grpc_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd) {
gpr_mu_lock(&pollset->mu);
pollset->vtable->add_fd(pollset, fd, 1);
pollset->vtable->add_fd(exec_ctx, pollset, fd, 1);
/* the following (enabled only in debug) will reacquire and then release
our lock - meaning that if the unlocking flag passed to del_fd above is
not respected, the code will deadlock (in a way that we have a chance of
@ -152,9 +154,10 @@ void grpc_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd) {
#endif
}
void grpc_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) {
void grpc_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd) {
gpr_mu_lock(&pollset->mu);
pollset->vtable->del_fd(pollset, fd, 1);
pollset->vtable->del_fd(exec_ctx, pollset, fd, 1);
/* the following (enabled only in debug) will reacquire and then release
our lock - meaning that if the unlocking flag passed to del_fd above is
not respected, the code will deadlock (in a way that we have a chance of
@ -165,23 +168,28 @@ void grpc_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd) {
#endif
}
static void finish_shutdown(grpc_pollset *pollset) {
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {
GPR_ASSERT(grpc_closure_list_empty(pollset->idle_jobs));
pollset->vtable->finish_shutdown(pollset);
pollset->shutdown_done_cb(pollset->shutdown_done_arg);
grpc_exec_ctx_enqueue(exec_ctx, pollset->shutdown_done, 1);
}
void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec now, gpr_timespec deadline) {
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker *worker, gpr_timespec now,
gpr_timespec deadline) {
/* pollset->mu already held */
int added_worker = 0;
int locked = 1;
/* this must happen before we (potentially) drop pollset->mu */
worker->next = worker->prev = NULL;
/* TODO(ctiller): pool these */
grpc_wakeup_fd_init(&worker->wakeup_fd);
if (grpc_maybe_call_delayed_callbacks(&pollset->mu, 1)) {
if (!grpc_pollset_has_workers(pollset) &&
!grpc_closure_list_empty(pollset->idle_jobs)) {
grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs);
goto done;
}
if (grpc_alarm_check(&pollset->mu, now, &deadline)) {
if (grpc_alarm_check(exec_ctx, now, &deadline)) {
goto done;
}
if (pollset->shutting_down) {
@ -190,19 +198,28 @@ void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
if (pollset->in_flight_cbs) {
/* Give do_promote priority so we don't starve it out */
gpr_mu_unlock(&pollset->mu);
gpr_mu_lock(&pollset->mu);
locked = 0;
goto done;
}
if (!pollset->kicked_without_pollers) {
push_front_worker(pollset, worker);
added_worker = 1;
gpr_tls_set(&g_current_thread_poller, (gpr_intptr)pollset);
pollset->vtable->maybe_work(pollset, worker, deadline, now, 1);
gpr_tls_set(&g_current_thread_worker, (gpr_intptr)worker);
pollset->vtable->maybe_work_and_unlock(exec_ctx, pollset, worker, deadline,
now);
locked = 0;
gpr_tls_set(&g_current_thread_poller, 0);
gpr_tls_set(&g_current_thread_worker, 0);
} else {
pollset->kicked_without_pollers = 0;
}
done:
if (!locked) {
grpc_exec_ctx_flush(exec_ctx);
gpr_mu_lock(&pollset->mu);
locked = 1;
}
grpc_wakeup_fd_destroy(&worker->wakeup_fd);
if (added_worker) {
remove_worker(pollset, worker);
@ -213,19 +230,24 @@ done:
} else if (!pollset->called_shutdown && pollset->in_flight_cbs == 0) {
pollset->called_shutdown = 1;
gpr_mu_unlock(&pollset->mu);
finish_shutdown(pollset);
finish_shutdown(exec_ctx, pollset);
grpc_exec_ctx_flush(exec_ctx);
/* Continuing to access pollset here is safe -- it is the caller's
* responsibility to not destroy when it has outstanding calls to
* grpc_pollset_work.
* TODO(dklempner): Can we refactor the shutdown logic to avoid this? */
gpr_mu_lock(&pollset->mu);
} else if (!grpc_closure_list_empty(pollset->idle_jobs)) {
gpr_mu_unlock(&pollset->mu);
grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs);
grpc_exec_ctx_flush(exec_ctx);
gpr_mu_lock(&pollset->mu);
}
}
}
void grpc_pollset_shutdown(grpc_pollset *pollset,
void (*shutdown_done)(void *arg),
void *shutdown_done_arg) {
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure) {
int call_shutdown = 0;
gpr_mu_lock(&pollset->mu);
GPR_ASSERT(!pollset->shutting_down);
@ -235,13 +257,15 @@ void grpc_pollset_shutdown(grpc_pollset *pollset,
pollset->called_shutdown = 1;
call_shutdown = 1;
}
pollset->shutdown_done_cb = shutdown_done;
pollset->shutdown_done_arg = shutdown_done_arg;
if (!grpc_pollset_has_workers(pollset)) {
grpc_exec_ctx_enqueue_list(exec_ctx, &pollset->idle_jobs);
}
pollset->shutdown_done = closure;
grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
gpr_mu_unlock(&pollset->mu);
if (call_shutdown) {
finish_shutdown(pollset);
finish_shutdown(exec_ctx, pollset);
}
}
@ -279,15 +303,14 @@ typedef struct grpc_unary_promote_args {
const grpc_pollset_vtable *original_vtable;
grpc_pollset *pollset;
grpc_fd *fd;
grpc_iomgr_closure promotion_closure;
grpc_closure promotion_closure;
} grpc_unary_promote_args;
static void basic_do_promote(void *args, int success) {
static void basic_do_promote(grpc_exec_ctx *exec_ctx, void *args, int success) {
grpc_unary_promote_args *up_args = args;
const grpc_pollset_vtable *original_vtable = up_args->original_vtable;
grpc_pollset *pollset = up_args->pollset;
grpc_fd *fd = up_args->fd;
int do_shutdown_cb = 0;
/*
* This is quite tricky. There are a number of cases to keep in mind here:
@ -300,12 +323,7 @@ static void basic_do_promote(void *args, int success) {
gpr_mu_lock(&pollset->mu);
/* First we need to ensure that nobody is polling concurrently */
if (grpc_pollset_has_workers(pollset)) {
grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
grpc_iomgr_add_callback(&up_args->promotion_closure);
gpr_mu_unlock(&pollset->mu);
return;
}
GPR_ASSERT(!grpc_pollset_has_workers(pollset));
gpr_free(up_args);
/* At this point the pollset may no longer be a unary poller. In that case
@ -317,21 +335,20 @@ static void basic_do_promote(void *args, int success) {
if (pollset->shutting_down) {
/* We don't care about this pollset anymore. */
if (pollset->in_flight_cbs == 0 && !pollset->called_shutdown) {
GPR_ASSERT(!grpc_pollset_has_workers(pollset));
pollset->called_shutdown = 1;
do_shutdown_cb = 1;
finish_shutdown(exec_ctx, pollset);
}
} else if (grpc_fd_is_orphaned(fd)) {
/* Don't try to add it to anything, we'll drop our ref on it below */
} else if (pollset->vtable != original_vtable) {
pollset->vtable->add_fd(pollset, fd, 0);
pollset->vtable->add_fd(exec_ctx, pollset, fd, 0);
} else if (fd != pollset->data.ptr) {
grpc_fd *fds[2];
fds[0] = pollset->data.ptr;
fds[1] = fd;
if (fds[0] && !grpc_fd_is_orphaned(fds[0])) {
grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
grpc_platform_become_multipoller(exec_ctx, pollset, fds,
GPR_ARRAY_SIZE(fds));
GRPC_FD_UNREF(fds[0], "basicpoll");
} else {
/* old fd is orphaned and we haven't cleaned it up until now, so remain a
@ -346,16 +363,12 @@ static void basic_do_promote(void *args, int success) {
gpr_mu_unlock(&pollset->mu);
if (do_shutdown_cb) {
pollset->shutdown_done_cb(pollset->shutdown_done_arg);
}
/* Matching ref in basic_pollset_add_fd */
GRPC_FD_UNREF(fd, "basicpoll_add");
}
static void basic_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd,
int and_unlock_pollset) {
static void basic_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd, int and_unlock_pollset) {
grpc_unary_promote_args *up_args;
GPR_ASSERT(fd);
if (fd == pollset->data.ptr) goto exit;
@ -372,7 +385,8 @@ static void basic_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd,
pollset->data.ptr = fd;
GRPC_FD_REF(fd, "basicpoll");
} else if (!grpc_fd_is_orphaned(fds[0])) {
grpc_platform_become_multipoller(pollset, fds, GPR_ARRAY_SIZE(fds));
grpc_platform_become_multipoller(exec_ctx, pollset, fds,
GPR_ARRAY_SIZE(fds));
GRPC_FD_UNREF(fds[0], "basicpoll");
} else {
/* old fd is orphaned and we haven't cleaned it up until now, so remain a
@ -389,13 +403,13 @@ static void basic_pollset_add_fd(grpc_pollset *pollset, grpc_fd *fd,
GRPC_FD_REF(fd, "basicpoll_add");
pollset->in_flight_cbs++;
up_args = gpr_malloc(sizeof(*up_args));
up_args->pollset = pollset;
up_args->fd = fd;
up_args->original_vtable = pollset->vtable;
up_args->pollset = pollset;
up_args->promotion_closure.cb = basic_do_promote;
up_args->promotion_closure.cb_arg = up_args;
grpc_iomgr_add_callback(&up_args->promotion_closure);
grpc_closure_list_add(&pollset->idle_jobs, &up_args->promotion_closure, 1);
grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
exit:
@ -404,8 +418,8 @@ exit:
}
}
static void basic_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd,
int and_unlock_pollset) {
static void basic_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_fd *fd, int and_unlock_pollset) {
GPR_ASSERT(fd);
if (fd == pollset->data.ptr) {
GRPC_FD_UNREF(pollset->data.ptr, "basicpoll");
@ -417,10 +431,11 @@ static void basic_pollset_del_fd(grpc_pollset *pollset, grpc_fd *fd,
}
}
static void basic_pollset_maybe_work(grpc_pollset *pollset,
grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now,
int allow_synchronous_callback) {
static void basic_pollset_maybe_work_and_unlock(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
grpc_pollset_worker *worker,
gpr_timespec deadline,
gpr_timespec now) {
struct pollfd pfd[2];
grpc_fd *fd;
grpc_fd_watcher fd_watcher;
@ -457,7 +472,7 @@ static void basic_pollset_maybe_work(grpc_pollset *pollset,
GRPC_TIMER_MARK(GRPC_PTAG_POLL_FINISHED, r);
if (fd) {
grpc_fd_end_poll(&fd_watcher, pfd[1].revents & POLLIN,
grpc_fd_end_poll(exec_ctx, &fd_watcher, pfd[1].revents & POLLIN,
pfd[1].revents & POLLOUT);
}
@ -473,15 +488,13 @@ static void basic_pollset_maybe_work(grpc_pollset *pollset,
}
if (nfds > 1) {
if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
grpc_fd_become_readable(fd, allow_synchronous_callback);
grpc_fd_become_readable(exec_ctx, fd);
}
if (pfd[1].revents & (POLLOUT | POLLHUP | POLLERR)) {
grpc_fd_become_writable(fd, allow_synchronous_callback);
grpc_fd_become_writable(exec_ctx, fd);
}
}
}
gpr_mu_lock(&pollset->mu);
}
static void basic_pollset_destroy(grpc_pollset *pollset) {
@ -492,8 +505,9 @@ static void basic_pollset_destroy(grpc_pollset *pollset) {
}
static const grpc_pollset_vtable basic_pollset = {
basic_pollset_add_fd, basic_pollset_del_fd, basic_pollset_maybe_work,
basic_pollset_destroy, basic_pollset_destroy};
basic_pollset_add_fd, basic_pollset_del_fd,
basic_pollset_maybe_work_and_unlock, basic_pollset_destroy,
basic_pollset_destroy};
static void become_basic_pollset(grpc_pollset *pollset, grpc_fd *fd_or_null) {
pollset->vtable = &basic_pollset;

@ -37,6 +37,8 @@
#include <poll.h>
#include <grpc/support/sync.h>
#include "src/core/iomgr/exec_ctx.h"
#include "src/core/iomgr/iomgr.h"
#include "src/core/iomgr/wakeup_fd_posix.h"
typedef struct grpc_pollset_vtable grpc_pollset_vtable;
@ -64,8 +66,8 @@ typedef struct grpc_pollset {
int shutting_down;
int called_shutdown;
int kicked_without_pollers;
void (*shutdown_done_cb)(void *arg);
void *shutdown_done_arg;
grpc_closure *shutdown_done;
grpc_closure_list idle_jobs;
union {
int fd;
void *ptr;
@ -73,13 +75,13 @@ typedef struct grpc_pollset {
} grpc_pollset;
struct grpc_pollset_vtable {
void (*add_fd)(grpc_pollset *pollset, struct grpc_fd *fd,
int and_unlock_pollset);
void (*del_fd)(grpc_pollset *pollset, struct grpc_fd *fd,
int and_unlock_pollset);
void (*maybe_work)(grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now,
int allow_synchronous_callback);
void (*add_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
struct grpc_fd *fd, int and_unlock_pollset);
void (*del_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
struct grpc_fd *fd, int and_unlock_pollset);
void (*maybe_work_and_unlock)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker *worker,
gpr_timespec deadline, gpr_timespec now);
void (*finish_shutdown)(grpc_pollset *pollset);
void (*destroy)(grpc_pollset *pollset);
};
@ -87,10 +89,12 @@ struct grpc_pollset_vtable {
#define GRPC_POLLSET_MU(pollset) (&(pollset)->mu)
/* Add an fd to a pollset */
void grpc_pollset_add_fd(grpc_pollset *pollset, struct grpc_fd *fd);
void grpc_pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
struct grpc_fd *fd);
/* Force remove an fd from a pollset (normally they are removed on the next
poll after an fd is orphaned) */
void grpc_pollset_del_fd(grpc_pollset *pollset, struct grpc_fd *fd);
void grpc_pollset_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
struct grpc_fd *fd);
/* Returns the fd to listen on for kicks */
int grpc_kick_read_fd(grpc_pollset *p);
@ -108,12 +112,14 @@ int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
gpr_timespec now);
/* turn a pollset into a multipoller: platform specific */
typedef void (*grpc_platform_become_multipoller_type)(grpc_pollset *pollset,
typedef void (*grpc_platform_become_multipoller_type)(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset,
struct grpc_fd **fds,
size_t fd_count);
extern grpc_platform_become_multipoller_type grpc_platform_become_multipoller;
void grpc_poll_become_multipoller(grpc_pollset *pollset, struct grpc_fd **fds,
void grpc_poll_become_multipoller(grpc_exec_ctx *exec_ctx,
grpc_pollset *pollset, struct grpc_fd **fds,
size_t fd_count);
/* Return 1 if the pollset has active threads in grpc_pollset_work (pollset must

@ -49,11 +49,13 @@
#include "src/core/iomgr/pollset_set_windows.h"
#endif
void grpc_pollset_set_init(grpc_pollset_set *pollset_set);
void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set);
void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
grpc_pollset *pollset);
void grpc_pollset_set_del_pollset(grpc_pollset_set *pollset_set,
grpc_pollset *pollset);
void grpc_pollset_set_init(grpc_pollset_set* pollset_set);
void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set);
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set,
grpc_pollset* pollset);
void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set,
grpc_pollset* pollset);
#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_H */

@ -58,7 +58,8 @@ void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {
gpr_free(pollset_set->fds);
}
void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
void grpc_pollset_set_add_pollset(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set,
grpc_pollset *pollset) {
size_t i, j;
gpr_mu_lock(&pollset_set->mu);
@ -74,7 +75,7 @@ void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
if (grpc_fd_is_orphaned(pollset_set->fds[i])) {
GRPC_FD_UNREF(pollset_set->fds[i], "pollset");
} else {
grpc_pollset_add_fd(pollset, pollset_set->fds[i]);
grpc_pollset_add_fd(exec_ctx, pollset, pollset_set->fds[i]);
pollset_set->fds[j++] = pollset_set->fds[i];
}
}
@ -82,7 +83,8 @@ void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
gpr_mu_unlock(&pollset_set->mu);
}
void grpc_pollset_set_del_pollset(grpc_pollset_set *pollset_set,
void grpc_pollset_set_del_pollset(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set,
grpc_pollset *pollset) {
size_t i;
gpr_mu_lock(&pollset_set->mu);
@ -97,7 +99,8 @@ void grpc_pollset_set_del_pollset(grpc_pollset_set *pollset_set,
gpr_mu_unlock(&pollset_set->mu);
}
void grpc_pollset_set_add_fd(grpc_pollset_set *pollset_set, grpc_fd *fd) {
void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_fd *fd) {
size_t i;
gpr_mu_lock(&pollset_set->mu);
if (pollset_set->fd_count == pollset_set->fd_capacity) {
@ -108,12 +111,13 @@ void grpc_pollset_set_add_fd(grpc_pollset_set *pollset_set, grpc_fd *fd) {
GRPC_FD_REF(fd, "pollset_set");
pollset_set->fds[pollset_set->fd_count++] = fd;
for (i = 0; i < pollset_set->pollset_count; i++) {
grpc_pollset_add_fd(pollset_set->pollsets[i], fd);
grpc_pollset_add_fd(exec_ctx, pollset_set->pollsets[i], fd);
}
gpr_mu_unlock(&pollset_set->mu);
}
void grpc_pollset_set_del_fd(grpc_pollset_set *pollset_set, grpc_fd *fd) {
void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_fd *fd) {
size_t i;
gpr_mu_lock(&pollset_set->mu);
for (i = 0; i < pollset_set->fd_count; i++) {

@ -49,7 +49,9 @@ typedef struct grpc_pollset_set {
grpc_fd **fds;
} grpc_pollset_set;
void grpc_pollset_set_add_fd(grpc_pollset_set *pollset_set, grpc_fd *fd);
void grpc_pollset_set_del_fd(grpc_pollset_set *pollset_set, grpc_fd *fd);
void grpc_pollset_set_add_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_fd *fd);
void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
grpc_pollset_set *pollset_set, grpc_fd *fd);
#endif /* GRPC_INTERNAL_CORE_IOMGR_POLLSET_WINDOWS_H */

@ -37,14 +37,16 @@
#include "src/core/iomgr/pollset_set.h"
void grpc_pollset_set_init(grpc_pollset_set *pollset_set) {}
void grpc_pollset_set_init(grpc_pollset_set* pollset_set) {}
void grpc_pollset_set_destroy(grpc_pollset_set *pollset_set) {}
void grpc_pollset_set_destroy(grpc_pollset_set* pollset_set) {}
void grpc_pollset_set_add_pollset(grpc_pollset_set *pollset_set,
grpc_pollset *pollset) {}
void grpc_pollset_set_add_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set,
grpc_pollset* pollset) {}
void grpc_pollset_set_del_pollset(grpc_pollset_set *pollset_set,
grpc_pollset *pollset) {}
void grpc_pollset_set_del_pollset(grpc_exec_ctx* exec_ctx,
grpc_pollset_set* pollset_set,
grpc_pollset* pollset) {}
#endif /* GPR_WINSOCK_SOCKET */

@ -85,29 +85,26 @@ void grpc_pollset_init(grpc_pollset *pollset) {
pollset->kicked_without_pollers = 0;
}
void grpc_pollset_shutdown(grpc_pollset *pollset,
void (*shutdown_done)(void *arg),
void *shutdown_done_arg) {
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure) {
gpr_mu_lock(&pollset->mu);
pollset->shutting_down = 1;
grpc_pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST);
gpr_mu_unlock(&pollset->mu);
shutdown_done(shutdown_done_arg);
grpc_exec_ctx_enqueue(exec_ctx, closure, 1);
}
void grpc_pollset_destroy(grpc_pollset *pollset) {
gpr_mu_destroy(&pollset->mu);
}
void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
gpr_timespec now, gpr_timespec deadline) {
void grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_pollset_worker *worker, gpr_timespec now,
gpr_timespec deadline) {
int added_worker = 0;
worker->next = worker->prev = NULL;
gpr_cv_init(&worker->cv);
if (grpc_maybe_call_delayed_callbacks(&pollset->mu, 1 /* GPR_TRUE */)) {
goto done;
}
if (grpc_alarm_check(&pollset->mu, now, &deadline)) {
if (grpc_alarm_check(exec_ctx, now, &deadline)) {
goto done;
}
if (!pollset->kicked_without_pollers && !pollset->shutting_down) {
@ -118,6 +115,11 @@ void grpc_pollset_work(grpc_pollset *pollset, grpc_pollset_worker *worker,
pollset->kicked_without_pollers = 0;
}
done:
if (!grpc_closure_list_empty(exec_ctx->closure_list)) {
gpr_mu_unlock(&pollset->mu);
grpc_exec_ctx_flush(exec_ctx);
gpr_mu_lock(&pollset->mu);
}
gpr_cv_destroy(&worker->cv);
if (added_worker) {
remove_worker(pollset, worker);

@ -35,6 +35,8 @@
#define GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H
#include <stddef.h>
#include "src/core/iomgr/exec_ctx.h"
#include "src/core/iomgr/iomgr.h"
#define GRPC_MAX_SOCKADDR_SIZE 128
@ -52,7 +54,8 @@ typedef struct {
On success: addresses is the result, and the callee must call
grpc_resolved_addresses_destroy when it's done with them
On failure: addresses is NULL */
typedef void (*grpc_resolve_cb)(void *arg, grpc_resolved_addresses *addresses);
typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses);
/* Asynchronously resolve addr. Use default_port if a port isn't designated
in addr, otherwise use the port in addr. */
/* TODO(ctiller): add a timeout here */

@ -144,17 +144,19 @@ done:
}
/* Thread function to asynch-ify grpc_blocking_resolve_address */
static void do_request(void *rp) {
static void do_request_thread(void *rp) {
request *r = rp;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resolved_addresses *resolved =
grpc_blocking_resolve_address(r->name, r->default_port);
void *arg = r->arg;
grpc_resolve_cb cb = r->cb;
gpr_free(r->name);
gpr_free(r->default_port);
cb(arg, resolved);
cb(&exec_ctx, arg, resolved);
grpc_iomgr_unregister_object(&r->iomgr_object);
gpr_free(r);
grpc_exec_ctx_finish(&exec_ctx);
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
@ -175,7 +177,7 @@ void grpc_resolve_address(const char *name, const char *default_port,
r->default_port = gpr_strdup(default_port);
r->cb = cb;
r->arg = arg;
gpr_thd_new(&id, do_request, r, NULL);
gpr_thd_new(&id, do_request_thread, r, NULL);
}
#endif

@ -128,6 +128,7 @@ done:
/* Thread function to asynch-ify grpc_blocking_resolve_address */
static void do_request(void *rp) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
request *r = rp;
grpc_resolved_addresses *resolved =
grpc_blocking_resolve_address(r->name, r->default_port);
@ -137,7 +138,8 @@ static void do_request(void *rp) {
gpr_free(r->default_port);
grpc_iomgr_unregister_object(&r->iomgr_object);
gpr_free(r);
cb(arg, resolved);
cb(&exec_ctx, arg, resolved);
grpc_exec_ctx_finish(&exec_ctx);
}
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
@ -149,7 +151,7 @@ void grpc_resolve_address(const char *name, const char *default_port,
grpc_resolve_cb cb, void *arg) {
request *r = gpr_malloc(sizeof(request));
gpr_thd_id id;
const char *label;
char *label;
gpr_asprintf(&label, "resolve:%s", name);
grpc_iomgr_register_object(&r->iomgr_object, label);
gpr_free(label);

@ -158,8 +158,10 @@ int grpc_sockaddr_to_string(char **out, const struct sockaddr *addr,
ip = &addr6->sin6_addr;
port = ntohs(addr6->sin6_port);
}
/* Windows inet_ntop wants a mutable ip pointer */
if (ip != NULL &&
inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != NULL) {
inet_ntop(addr->sa_family, (void *)ip, ntop_buf, sizeof(ntop_buf)) !=
NULL) {
ret = gpr_join_host_port(out, ntop_buf, port);
} else {
ret = gpr_asprintf(out, "(sockaddr family=%d)", addr->sa_family);

@ -82,7 +82,8 @@ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
DisconnectEx(winsocket->socket, NULL, 0, 0);
} else {
char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s", utf8_message);
gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s",
utf8_message);
gpr_free(utf8_message);
}
closesocket(winsocket->socket);

@ -41,6 +41,7 @@
#include <grpc/support/atm.h>
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/exec_ctx.h"
/* This holds the data for an outstanding read or write on a socket.
The mutex to protect the concurrent access to that data is the one
@ -54,8 +55,7 @@ typedef struct grpc_winsocket_callback_info {
OVERLAPPED overlapped;
/* The callback information for the pending operation. May be empty if the
caller hasn't registered a callback yet. */
void (*cb)(void *opaque, int success);
void *opaque;
grpc_closure *closure;
/* A boolean to describe if the IO Completion Port got a notification for
that operation. This will happen if the operation completed before the
called had time to register a callback. We could avoid that behavior
@ -91,7 +91,7 @@ typedef struct grpc_winsocket {
This prevents that. */
int added_to_iocp;
grpc_iomgr_closure shutdown_closure;
grpc_closure shutdown_closure;
/* A label for iomgr to track outstanding objects */
grpc_iomgr_object iomgr_object;

@ -44,8 +44,9 @@
NULL on failure).
interested_parties points to a set of pollsets that would be interested
in this connection being established (in order to continue their work) */
void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
void *arg, grpc_pollset_set *interested_parties,
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_connect,
grpc_endpoint **endpoint,
grpc_pollset_set *interested_parties,
const struct sockaddr *addr, size_t addr_len,
gpr_timespec deadline);

@ -57,16 +57,16 @@
extern int grpc_tcp_trace;
typedef struct {
void (*cb)(void *arg, grpc_endpoint *tcp);
void *cb_arg;
gpr_mu mu;
grpc_fd *fd;
gpr_timespec deadline;
grpc_alarm alarm;
int refs;
grpc_iomgr_closure write_closure;
grpc_closure write_closure;
grpc_pollset_set *interested_parties;
char *addr_str;
grpc_endpoint **ep;
grpc_closure *closure;
} async_connect;
static int prepare_socket(const struct sockaddr *addr, int fd) {
@ -91,7 +91,7 @@ error:
return 0;
}
static void tc_on_alarm(void *acp, int success) {
static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, int success) {
int done;
async_connect *ac = acp;
if (grpc_tcp_trace) {
@ -100,7 +100,7 @@ static void tc_on_alarm(void *acp, int success) {
}
gpr_mu_lock(&ac->mu);
if (ac->fd != NULL) {
grpc_fd_shutdown(ac->fd);
grpc_fd_shutdown(exec_ctx, ac->fd);
}
done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu);
@ -111,15 +111,14 @@ static void tc_on_alarm(void *acp, int success) {
}
}
static void on_writable(void *acp, int success) {
static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, int success) {
async_connect *ac = acp;
int so_error = 0;
socklen_t so_error_size;
int err;
int done;
grpc_endpoint *ep = NULL;
void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb;
void *cb_arg = ac->cb_arg;
grpc_endpoint **ep = ac->ep;
grpc_closure *closure = ac->closure;
grpc_fd *fd;
if (grpc_tcp_trace) {
@ -133,7 +132,7 @@ static void on_writable(void *acp, int success) {
ac->fd = NULL;
gpr_mu_unlock(&ac->mu);
grpc_alarm_cancel(&ac->alarm);
grpc_alarm_cancel(exec_ctx, &ac->alarm);
gpr_mu_lock(&ac->mu);
if (success) {
@ -162,7 +161,7 @@ static void on_writable(void *acp, int success) {
don't do that! */
gpr_log(GPR_ERROR, "kernel out of buffers");
gpr_mu_unlock(&ac->mu);
grpc_fd_notify_on_write(fd, &ac->write_closure);
grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure);
return;
} else {
switch (so_error) {
@ -176,8 +175,8 @@ static void on_writable(void *acp, int success) {
goto finish;
}
} else {
grpc_pollset_set_del_fd(ac->interested_parties, fd);
ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
*ep = grpc_tcp_create(fd, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, ac->addr_str);
fd = NULL;
goto finish;
}
@ -190,8 +189,8 @@ static void on_writable(void *acp, int success) {
finish:
if (fd != NULL) {
grpc_pollset_set_del_fd(ac->interested_parties, fd);
grpc_fd_orphan(fd, NULL, "tcp_client_orphan");
grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd);
grpc_fd_orphan(exec_ctx, fd, NULL, "tcp_client_orphan");
fd = NULL;
}
done = (--ac->refs == 0);
@ -201,11 +200,12 @@ finish:
gpr_free(ac->addr_str);
gpr_free(ac);
}
cb(cb_arg, ep);
grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL);
}
void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
void *arg, grpc_pollset_set *interested_parties,
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_endpoint **ep,
grpc_pollset_set *interested_parties,
const struct sockaddr *addr, size_t addr_len,
gpr_timespec deadline) {
int fd;
@ -218,6 +218,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
char *name;
char *addr_str;
*ep = NULL;
/* Use dualstack sockets where available. */
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
addr = (const struct sockaddr *)&addr6_v4mapped;
@ -235,7 +237,7 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
addr_len = sizeof(addr4_copy);
}
if (!prepare_socket(addr, fd)) {
cb(arg, NULL);
grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
return;
}
@ -250,22 +252,23 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
fdobj = grpc_fd_create(fd, name);
if (err >= 0) {
cb(arg, grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
*ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
grpc_exec_ctx_enqueue(exec_ctx, closure, 1);
goto done;
}
if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
grpc_fd_orphan(fdobj, NULL, "tcp_client_connect_error");
cb(arg, NULL);
grpc_fd_orphan(exec_ctx, fdobj, NULL, "tcp_client_connect_error");
grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
goto done;
}
grpc_pollset_set_add_fd(interested_parties, fdobj);
grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);
ac = gpr_malloc(sizeof(async_connect));
ac->cb = cb;
ac->cb_arg = arg;
ac->closure = closure;
ac->ep = ep;
ac->fd = fdobj;
ac->interested_parties = interested_parties;
ac->addr_str = addr_str;
@ -281,10 +284,10 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
}
gpr_mu_lock(&ac->mu);
grpc_alarm_init(&ac->alarm,
grpc_alarm_init(exec_ctx, &ac->alarm,
gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
gpr_mu_unlock(&ac->mu);
done:

@ -52,14 +52,15 @@
#include "src/core/iomgr/socket_windows.h"
typedef struct {
void (*cb)(void *arg, grpc_endpoint *tcp);
void *cb_arg;
grpc_closure *on_done;
gpr_mu mu;
grpc_winsocket *socket;
gpr_timespec deadline;
grpc_alarm alarm;
char *addr_name;
int refs;
grpc_closure on_connect;
grpc_endpoint **endpoint;
} async_connect;
static void async_connect_unlock_and_cleanup(async_connect *ac) {
@ -73,7 +74,7 @@ static void async_connect_unlock_and_cleanup(async_connect *ac) {
}
}
static void on_alarm(void *acp, int occured) {
static void on_alarm(grpc_exec_ctx *exec_ctx, void *acp, int occured) {
async_connect *ac = acp;
gpr_mu_lock(&ac->mu);
/* If the alarm didn't occur, it got cancelled. */
@ -83,15 +84,14 @@ static void on_alarm(void *acp, int occured) {
async_connect_unlock_and_cleanup(ac);
}
static void on_connect(void *acp, int from_iocp) {
static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, int from_iocp) {
async_connect *ac = acp;
SOCKET sock = ac->socket->socket;
grpc_endpoint *ep = NULL;
grpc_endpoint **ep = ac->endpoint;
grpc_winsocket_callback_info *info = &ac->socket->write_info;
void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb;
void *cb_arg = ac->cb_arg;
grpc_alarm_cancel(&ac->alarm);
grpc_closure *on_done = ac->on_done;
grpc_alarm_cancel(exec_ctx, &ac->alarm);
gpr_mu_lock(&ac->mu);
@ -106,7 +106,7 @@ static void on_connect(void *acp, int from_iocp) {
gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
gpr_free(utf8_message);
} else {
ep = grpc_tcp_create(ac->socket, ac->addr_name);
*ep = grpc_tcp_create(ac->socket, ac->addr_name);
ac->socket = NULL;
}
}
@ -114,13 +114,14 @@ static void on_connect(void *acp, int from_iocp) {
async_connect_unlock_and_cleanup(ac);
/* If the connection was aborted, the callback was already called when
the deadline was met. */
cb(cb_arg, ep);
on_done->cb(exec_ctx, on_done->cb_arg, *ep != NULL);
}
/* Tries to issue one async connection, then schedules both an IOCP
notification request for the connection, and one timeout alert. */
void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
void *arg, grpc_pollset_set *interested_parties,
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *on_done,
grpc_endpoint **endpoint,
grpc_pollset_set *interested_parties,
const struct sockaddr *addr, size_t addr_len,
gpr_timespec deadline) {
SOCKET sock = INVALID_SOCKET;
@ -137,6 +138,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
char *utf8_message;
grpc_winsocket_callback_info *info;
*endpoint = NULL;
/* Use dualstack sockets where available. */
if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
addr = (const struct sockaddr *)&addr6_v4mapped;
@ -176,7 +179,8 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
socket = grpc_winsocket_create(sock, "client");
info = &socket->write_info;
success = ConnectEx(sock, addr, (int)addr_len, NULL, 0, NULL, &info->overlapped);
success =
ConnectEx(sock, addr, (int)addr_len, NULL, 0, NULL, &info->overlapped);
/* It wouldn't be unusual to get a success immediately. But we'll still get
an IOCP notification, so let's ignore it. */
@ -189,16 +193,17 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp),
}
ac = gpr_malloc(sizeof(async_connect));
ac->cb = cb;
ac->cb_arg = arg;
ac->on_done = on_done;
ac->socket = socket;
gpr_mu_init(&ac->mu);
ac->refs = 2;
ac->addr_name = grpc_sockaddr_to_uri(addr);
ac->endpoint = endpoint;
grpc_closure_init(&ac->on_connect, on_connect, ac);
grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac,
grpc_alarm_init(exec_ctx, &ac->alarm, deadline, on_alarm, ac,
gpr_now(GPR_CLOCK_MONOTONIC));
grpc_socket_notify_on_write(socket, on_connect, ac);
grpc_socket_notify_on_write(exec_ctx, socket, &ac->on_connect);
return;
failure:
@ -210,7 +215,7 @@ failure:
} else if (sock != INVALID_SOCKET) {
closesocket(sock);
}
cb(arg, NULL);
grpc_exec_ctx_enqueue(exec_ctx, on_done, 0);
}
#endif /* GPR_WINSOCK_SOCKET */

@ -85,39 +85,42 @@ typedef struct {
/** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */
size_t outgoing_byte_idx;
grpc_iomgr_closure *read_cb;
grpc_iomgr_closure *write_cb;
grpc_closure *read_cb;
grpc_closure *write_cb;
grpc_iomgr_closure read_closure;
grpc_iomgr_closure write_closure;
grpc_closure read_closure;
grpc_closure write_closure;
char *peer_string;
} grpc_tcp;
static void tcp_handle_read(void *arg /* grpc_tcp */, int success);
static void tcp_handle_write(void *arg /* grpc_tcp */, int success);
static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
int success);
static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
int success);
static void tcp_shutdown(grpc_endpoint *ep) {
static void tcp_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_fd_shutdown(tcp->em_fd);
grpc_fd_shutdown(exec_ctx, tcp->em_fd);
}
static void tcp_free(grpc_tcp *tcp) {
grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan");
static void tcp_free(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
grpc_fd_orphan(exec_ctx, tcp->em_fd, NULL, "tcp_unref_orphan");
gpr_free(tcp->peer_string);
gpr_free(tcp);
}
/*#define GRPC_TCP_REFCOUNT_DEBUG*/
#ifdef GRPC_TCP_REFCOUNT_DEBUG
#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__)
#define TCP_UNREF(cl, tcp, reason) \
tcp_unref((cl), (tcp), (reason), __FILE__, __LINE__)
#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file,
int line) {
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp,
const char *reason, const char *file, int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
reason, tcp->refcount.count, tcp->refcount.count - 1);
if (gpr_unref(&tcp->refcount)) {
tcp_free(tcp);
tcp_free(exec_ctx, tcp);
}
}
@ -128,24 +131,24 @@ static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
gpr_ref(&tcp->refcount);
}
#else
#define TCP_UNREF(tcp, reason) tcp_unref((tcp))
#define TCP_UNREF(cl, tcp, reason) tcp_unref((cl), (tcp))
#define TCP_REF(tcp, reason) tcp_ref((tcp))
static void tcp_unref(grpc_tcp *tcp) {
static void tcp_unref(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
if (gpr_unref(&tcp->refcount)) {
tcp_free(tcp);
tcp_free(exec_ctx, tcp);
}
}
static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
#endif
static void tcp_destroy(grpc_endpoint *ep) {
static void tcp_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
TCP_UNREF(tcp, "destroy");
TCP_UNREF(exec_ctx, tcp, "destroy");
}
static void call_read_cb(grpc_tcp *tcp, int success) {
grpc_iomgr_closure *cb = tcp->read_cb;
static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, int success) {
grpc_closure *cb = tcp->read_cb;
if (grpc_tcp_trace) {
size_t i;
@ -160,11 +163,11 @@ static void call_read_cb(grpc_tcp *tcp, int success) {
tcp->read_cb = NULL;
tcp->incoming_buffer = NULL;
cb->cb(cb->cb_arg, success);
cb->cb(exec_ctx, cb->cb_arg, success);
}
#define MAX_READ_IOVEC 4
static void tcp_continue_read(grpc_tcp *tcp) {
static void tcp_continue_read(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp) {
struct msghdr msg;
struct iovec iov[MAX_READ_IOVEC];
ssize_t read_bytes;
@ -206,18 +209,18 @@ static void tcp_continue_read(grpc_tcp *tcp) {
tcp->iov_size /= 2;
}
/* We've consumed the edge, request a new one */
grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
} else {
/* TODO(klempner): Log interesting errors */
gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
call_read_cb(tcp, 0);
TCP_UNREF(tcp, "read");
call_read_cb(exec_ctx, tcp, 0);
TCP_UNREF(exec_ctx, tcp, "read");
}
} else if (read_bytes == 0) {
/* 0 read size ==> end of stream */
gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
call_read_cb(tcp, 0);
TCP_UNREF(tcp, "read");
call_read_cb(exec_ctx, tcp, 0);
TCP_UNREF(exec_ctx, tcp, "read");
} else {
GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length);
if ((size_t)read_bytes < tcp->incoming_buffer->length) {
@ -228,29 +231,29 @@ static void tcp_continue_read(grpc_tcp *tcp) {
++tcp->iov_size;
}
GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length);
call_read_cb(tcp, 1);
TCP_UNREF(tcp, "read");
call_read_cb(exec_ctx, tcp, 1);
TCP_UNREF(exec_ctx, tcp, "read");
}
GRPC_TIMER_END(GRPC_PTAG_HANDLE_READ, 0);
}
static void tcp_handle_read(void *arg /* grpc_tcp */, int success) {
static void tcp_handle_read(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
int success) {
grpc_tcp *tcp = (grpc_tcp *)arg;
GPR_ASSERT(!tcp->finished_edge);
if (!success) {
gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer);
call_read_cb(tcp, 0);
TCP_UNREF(tcp, "read");
call_read_cb(exec_ctx, tcp, 0);
TCP_UNREF(exec_ctx, tcp, "read");
} else {
tcp_continue_read(tcp);
tcp_continue_read(exec_ctx, tcp);
}
}
static grpc_endpoint_op_status tcp_read(grpc_endpoint *ep,
gpr_slice_buffer *incoming_buffer,
grpc_iomgr_closure *cb) {
static void tcp_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *incoming_buffer, grpc_closure *cb) {
grpc_tcp *tcp = (grpc_tcp *)ep;
GPR_ASSERT(tcp->read_cb == NULL);
tcp->read_cb = cb;
@ -259,16 +262,16 @@ static grpc_endpoint_op_status tcp_read(grpc_endpoint *ep,
TCP_REF(tcp, "read");
if (tcp->finished_edge) {
tcp->finished_edge = 0;
grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure);
grpc_fd_notify_on_read(exec_ctx, tcp->em_fd, &tcp->read_closure);
} else {
grpc_iomgr_add_delayed_callback(&tcp->read_closure, 1);
grpc_exec_ctx_enqueue(exec_ctx, &tcp->read_closure, 1);
}
/* TODO(ctiller): immediate return */
return GRPC_ENDPOINT_PENDING;
}
typedef enum { FLUSH_DONE, FLUSH_PENDING, FLUSH_ERROR } flush_result;
#define MAX_WRITE_IOVEC 16
static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) {
static flush_result tcp_flush(grpc_tcp *tcp) {
struct msghdr msg;
struct iovec iov[MAX_WRITE_IOVEC];
msg_iovlen_type iov_size;
@ -318,10 +321,10 @@ static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) {
if (errno == EAGAIN) {
tcp->outgoing_slice_idx = unwind_slice_idx;
tcp->outgoing_byte_idx = unwind_byte_idx;
return GRPC_ENDPOINT_PENDING;
return FLUSH_PENDING;
} else {
/* TODO(klempner): Log some of these */
return GRPC_ENDPOINT_ERROR;
return FLUSH_ERROR;
}
}
@ -342,42 +345,42 @@ static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) {
}
if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) {
return GRPC_ENDPOINT_DONE;
return FLUSH_DONE;
}
};
}
static void tcp_handle_write(void *arg /* grpc_tcp */, int success) {
static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */,
int success) {
grpc_tcp *tcp = (grpc_tcp *)arg;
grpc_endpoint_op_status status;
grpc_iomgr_closure *cb;
flush_result status;
grpc_closure *cb;
if (!success) {
cb = tcp->write_cb;
tcp->write_cb = NULL;
cb->cb(cb->cb_arg, 0);
TCP_UNREF(tcp, "write");
cb->cb(exec_ctx, cb->cb_arg, 0);
TCP_UNREF(exec_ctx, tcp, "write");
return;
}
GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_CB_WRITE, 0);
status = tcp_flush(tcp);
if (status == GRPC_ENDPOINT_PENDING) {
grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure);
if (status == FLUSH_PENDING) {
grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
} else {
cb = tcp->write_cb;
tcp->write_cb = NULL;
cb->cb(cb->cb_arg, status == GRPC_ENDPOINT_DONE);
TCP_UNREF(tcp, "write");
cb->cb(exec_ctx, cb->cb_arg, status == FLUSH_DONE);
TCP_UNREF(exec_ctx, tcp, "write");
}
GRPC_TIMER_END(GRPC_PTAG_TCP_CB_WRITE, 0);
}
static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep,
gpr_slice_buffer *buf,
grpc_iomgr_closure *cb) {
static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *buf, grpc_closure *cb) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_endpoint_op_status status;
flush_result status;
if (grpc_tcp_trace) {
size_t i;
@ -395,32 +398,35 @@ static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep,
if (buf->length == 0) {
GRPC_TIMER_END(GRPC_PTAG_TCP_WRITE, 0);
return GRPC_ENDPOINT_DONE;
grpc_exec_ctx_enqueue(exec_ctx, cb, 1);
return;
}
tcp->outgoing_buffer = buf;
tcp->outgoing_slice_idx = 0;
tcp->outgoing_byte_idx = 0;
status = tcp_flush(tcp);
if (status == GRPC_ENDPOINT_PENDING) {
if (status == FLUSH_PENDING) {
TCP_REF(tcp, "write");
tcp->write_cb = cb;
grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure);
grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure);
} else {
grpc_exec_ctx_enqueue(exec_ctx, cb, status == FLUSH_DONE);
}
GRPC_TIMER_END(GRPC_PTAG_TCP_WRITE, 0);
return status;
}
static void tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
static void tcp_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset *pollset) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_pollset_add_fd(pollset, tcp->em_fd);
grpc_pollset_add_fd(exec_ctx, pollset, tcp->em_fd);
}
static void tcp_add_to_pollset_set(grpc_endpoint *ep,
static void tcp_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset_set *pollset_set) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_pollset_set_add_fd(pollset_set, tcp->em_fd);
grpc_pollset_set_add_fd(exec_ctx, pollset_set, tcp->em_fd);
}
static char *tcp_get_peer(grpc_endpoint *ep) {

@ -40,14 +40,15 @@
typedef struct grpc_tcp_server grpc_tcp_server;
/* Called for newly connected TCP connections. */
typedef void (*grpc_tcp_server_cb)(void *arg, grpc_endpoint *ep);
typedef void (*grpc_tcp_server_cb)(grpc_exec_ctx *exec_ctx, void *arg,
grpc_endpoint *ep);
/* Create a server, initially not bound to any ports */
grpc_tcp_server *grpc_tcp_server_create(void);
/* Start listening to bound ports */
void grpc_tcp_server_start(grpc_tcp_server *server, grpc_pollset **pollsets,
size_t pollset_count,
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
grpc_pollset **pollsets, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb, void *cb_arg);
/* Add a port to the server, returning port number on success, or negative
@ -71,8 +72,7 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
up when grpc_tcp_server_destroy is called. */
int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index);
void grpc_tcp_server_destroy(grpc_tcp_server *server,
void (*shutdown_done)(void *shutdown_done_arg),
void *shutdown_done_arg);
void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
grpc_closure *closure);
#endif /* GRPC_INTERNAL_CORE_IOMGR_TCP_SERVER_H */

@ -84,8 +84,8 @@ typedef struct {
struct sockaddr_un un;
} addr;
size_t addr_len;
grpc_iomgr_closure read_closure;
grpc_iomgr_closure destroyed_closure;
grpc_closure read_closure;
grpc_closure destroyed_closure;
} server_port;
static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
@ -118,8 +118,7 @@ struct grpc_tcp_server {
size_t port_capacity;
/* shutdown callback */
void (*shutdown_complete)(void *);
void *shutdown_complete_arg;
grpc_closure *shutdown_complete;
/* all pollsets interested in new connections */
grpc_pollset **pollsets;
@ -141,9 +140,8 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
return s;
}
static void finish_shutdown(grpc_tcp_server *s) {
s->shutdown_complete(s->shutdown_complete_arg);
s->shutdown_complete = NULL;
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1);
gpr_mu_destroy(&s->mu);
@ -151,25 +149,23 @@ static void finish_shutdown(grpc_tcp_server *s) {
gpr_free(s);
}
static void destroyed_port(void *server, int success) {
static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, int success) {
grpc_tcp_server *s = server;
gpr_mu_lock(&s->mu);
s->destroyed_ports++;
if (s->destroyed_ports == s->nports) {
gpr_mu_unlock(&s->mu);
finish_shutdown(s);
finish_shutdown(exec_ctx, s);
} else {
GPR_ASSERT(s->destroyed_ports < s->nports);
gpr_mu_unlock(&s->mu);
}
}
static void dont_care_about_shutdown_completion(void *ignored) {}
/* called when all listening endpoints have been shutdown, so no further
events will be received on them - at this point it's safe to destroy
things */
static void deactivated_all_ports(grpc_tcp_server *s) {
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
size_t i;
/* delete ALL the things */
@ -188,38 +184,35 @@ static void deactivated_all_ports(grpc_tcp_server *s) {
}
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
grpc_fd_orphan(sp->emfd, &sp->destroyed_closure, "tcp_listener_shutdown");
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
"tcp_listener_shutdown");
}
gpr_mu_unlock(&s->mu);
} else {
gpr_mu_unlock(&s->mu);
finish_shutdown(s);
finish_shutdown(exec_ctx, s);
}
}
void grpc_tcp_server_destroy(
grpc_tcp_server *s, void (*shutdown_complete)(void *shutdown_complete_arg),
void *shutdown_complete_arg) {
void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_closure *closure) {
size_t i;
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->shutdown);
s->shutdown = 1;
s->shutdown_complete = shutdown_complete
? shutdown_complete
: dont_care_about_shutdown_completion;
s->shutdown_complete_arg = shutdown_complete_arg;
s->shutdown_complete = closure;
/* shutdown all fd's */
if (s->active_ports) {
for (i = 0; i < s->nports; i++) {
grpc_fd_shutdown(s->ports[i].emfd);
grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
}
gpr_mu_unlock(&s->mu);
} else {
gpr_mu_unlock(&s->mu);
deactivated_all_ports(s);
deactivated_all_ports(exec_ctx, s);
}
}
@ -304,7 +297,7 @@ error:
}
/* event manager callback when reads are ready */
static void on_read(void *arg, int success) {
static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
server_port *sp = arg;
grpc_fd *fdobj;
size_t i;
@ -320,14 +313,14 @@ static void on_read(void *arg, int success) {
char *addr_str;
char *name;
/* Note: If we ever decide to return this address to the user, remember to
strip off the ::ffff:0.0.0.0/96 prefix first. */
strip off the ::ffff:0.0.0.0/96 prefix first. */
int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
if (fd < 0) {
switch (errno) {
case EINTR:
continue;
case EAGAIN:
grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
return;
default:
gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
@ -349,10 +342,10 @@ static void on_read(void *arg, int success) {
of channels -- we certainly should not be automatically adding every
incoming channel to every pollset owned by the server */
for (i = 0; i < sp->server->pollset_count; i++) {
grpc_pollset_add_fd(sp->server->pollsets[i], fdobj);
grpc_pollset_add_fd(exec_ctx, sp->server->pollsets[i], fdobj);
}
sp->server->on_accept_cb(
sp->server->on_accept_cb_arg,
exec_ctx, sp->server->on_accept_cb_arg,
grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
gpr_free(name);
@ -365,7 +358,7 @@ error:
gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(sp->server);
deactivated_all_ports(exec_ctx, sp->server);
} else {
gpr_mu_unlock(&sp->server->mu);
}
@ -489,9 +482,10 @@ int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index) {
return (index < s->nports) ? s->ports[index].fd : -1;
}
void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollsets, size_t
pollset_count, grpc_tcp_server_cb on_accept_cb, void
*on_accept_cb_arg) {
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_pollset **pollsets, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb,
void *on_accept_cb_arg) {
size_t i, j;
GPR_ASSERT(on_accept_cb);
gpr_mu_lock(&s->mu);
@ -503,11 +497,12 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollsets, size_t
s->pollset_count = pollset_count;
for (i = 0; i < s->nports; i++) {
for (j = 0; j < pollset_count; j++) {
grpc_pollset_add_fd(pollsets[j], s->ports[i].emfd);
grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
}
s->ports[i].read_closure.cb = on_read;
s->ports[i].read_closure.cb_arg = &s->ports[i];
grpc_fd_notify_on_read(s->ports[i].emfd, &s->ports[i].read_closure);
grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
&s->ports[i].read_closure);
s->active_ports++;
}
gpr_mu_unlock(&s->mu);

@ -67,6 +67,8 @@ typedef struct server_port {
/* The cached AcceptEx for that port. */
LPFN_ACCEPTEX AcceptEx;
int shutting_down;
/* closure for socket notification of accept being ready */
grpc_closure on_accept;
} server_port;
/* the overall server */
@ -86,8 +88,7 @@ struct grpc_tcp_server {
size_t port_capacity;
/* shutdown callback */
void(*shutdown_complete)(void *);
void *shutdown_complete_arg;
grpc_closure *shutdown_complete;
};
/* Public function. Allocates the proper data structures to hold a
@ -107,14 +108,14 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
static void dont_care_about_shutdown_completion(void *arg) {}
static void finish_shutdown(grpc_tcp_server *s) {
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
size_t i;
s->shutdown_complete(s->shutdown_complete_arg);
grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1);
/* Now that the accepts have been aborted, we can destroy the sockets.
The IOCP won't get notified on these, so we can flag them as already
closed by the system. */
The IOCP won't get notified on these, so we can flag them as already
closed by the system. */
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
grpc_winsocket_destroy(sp->socket);
@ -124,17 +125,13 @@ static void finish_shutdown(grpc_tcp_server *s) {
}
/* Public function. Stops and destroys a grpc_tcp_server. */
void grpc_tcp_server_destroy(grpc_tcp_server *s,
void (*shutdown_complete)(void *shutdown_done_arg),
void *shutdown_complete_arg) {
void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_closure *shutdown_complete) {
size_t i;
int immediately_done = 0;
gpr_mu_lock(&s->mu);
s->shutdown_complete = shutdown_complete
? shutdown_complete
: dont_care_about_shutdown_completion;
s->shutdown_complete_arg = shutdown_complete_arg;
s->shutdown_complete = shutdown_complete;
/* First, shutdown all fd's. This will queue abortion calls for all
of the pending accepts due to the normal operation mechanism. */
@ -149,7 +146,7 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s,
gpr_mu_unlock(&s->mu);
if (immediately_done) {
finish_shutdown(s);
finish_shutdown(exec_ctx, s);
}
}
@ -201,26 +198,25 @@ error:
return -1;
}
static void decrement_active_ports_and_notify(server_port *sp) {
static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
server_port *sp) {
int notify = 0;
sp->shutting_down = 0;
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports && sp->server->shutdown_complete != NULL) {
if (0 == --sp->server->active_ports &&
sp->server->shutdown_complete != NULL) {
notify = 1;
}
gpr_mu_unlock(&sp->server->mu);
if (notify) {
finish_shutdown(sp->server);
finish_shutdown(exec_ctx, sp->server);
}
}
/* start_accept will reference that for the IOCP notification request. */
static void on_accept(void *arg, int from_iocp);
/* In order to do an async accept, we need to create a socket first which
will be the one assigned to the new incoming connection. */
static void start_accept(server_port *port) {
static void start_accept(grpc_exec_ctx *exec_ctx, server_port *port) {
SOCKET sock = INVALID_SOCKET;
char *message;
char *utf8_message;
@ -259,7 +255,7 @@ static void start_accept(server_port *port) {
/* We're ready to do the accept. Calling grpc_socket_notify_on_read may
immediately process an accept that happened in the meantime. */
port->new_socket = sock;
grpc_socket_notify_on_read(port->socket, on_accept, port);
grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
return;
failure:
@ -269,7 +265,7 @@ failure:
change is not seen by on_accept and we proceed to trying new accept,
but we fail there because the listening port has been closed in the
meantime. */
decrement_active_ports_and_notify(port);
decrement_active_ports_and_notify(exec_ctx, port);
return;
}
utf8_message = gpr_format_message(WSAGetLastError());
@ -279,7 +275,7 @@ failure:
}
/* Event manager callback when reads are ready. */
static void on_accept(void *arg, int from_iocp) {
static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) {
server_port *sp = arg;
SOCKET sock = sp->new_socket;
grpc_winsocket_callback_info *info = &sp->socket->read_info;
@ -301,7 +297,7 @@ static void on_accept(void *arg, int from_iocp) {
}
/* The IOCP notified us of a completed operation. Let's grab the results,
and act accordingly. */
and act accordingly. */
transfered_bytes = 0;
wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
&transfered_bytes, FALSE, &flags);
@ -309,7 +305,7 @@ static void on_accept(void *arg, int from_iocp) {
if (sp->shutting_down) {
/* During the shutdown case, we ARE expecting an error. So that's well,
and we can wake up the shutdown thread. */
decrement_active_ports_and_notify(sp);
decrement_active_ports_and_notify(exec_ctx, sp);
return;
} else {
char *utf8_message = gpr_format_message(WSAGetLastError());
@ -345,12 +341,12 @@ static void on_accept(void *arg, int from_iocp) {
/* The only time we should call our callback, is where we successfully
managed to accept a connection, and created an endpoint. */
if (ep) sp->server->on_accept_cb(sp->server->on_accept_cb_arg, ep);
if (ep) sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep);
/* As we were notified from the IOCP of one and exactly one accept,
the former socked we created has now either been destroy or assigned
to the new connection. We need to create a new one for the next
connection. */
start_accept(sp);
start_accept(exec_ctx, sp);
}
static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
@ -384,8 +380,9 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
/* append it to the list under a lock */
if (s->nports == s->port_capacity) {
s->port_capacity *= 2;
s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
/* too many ports, and we need to store their address in a closure */
/* TODO(ctiller): make server_port a linked list */
abort();
}
sp = &s->ports[s->nports++];
sp->server = s;
@ -393,6 +390,7 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
sp->shutting_down = 0;
sp->AcceptEx = AcceptEx;
sp->new_socket = INVALID_SOCKET;
grpc_closure_init(&sp->on_accept, on_accept, sp);
GPR_ASSERT(sp->socket);
gpr_mu_unlock(&s->mu);
}
@ -458,12 +456,13 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
return allocated_port;
}
SOCKET grpc_tcp_server_get_socket(grpc_tcp_server *s, unsigned index) {
SOCKET
grpc_tcp_server_get_socket(grpc_tcp_server *s, unsigned index) {
return (index < s->nports) ? s->ports[index].socket->socket : INVALID_SOCKET;
}
void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset,
size_t pollset_count,
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_pollset **pollset, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb,
void *on_accept_cb_arg) {
size_t i;
@ -474,7 +473,7 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset,
s->on_accept_cb = on_accept_cb;
s->on_accept_cb_arg = on_accept_cb_arg;
for (i = 0; i < s->nports; i++) {
start_accept(s->ports + i);
start_accept(exec_ctx, s->ports + i);
s->active_ports++;
}
gpr_mu_unlock(&s->mu);

@ -82,8 +82,11 @@ typedef struct grpc_tcp {
/* Refcounting how many operations are in progress. */
gpr_refcount refcount;
grpc_iomgr_closure *read_cb;
grpc_iomgr_closure *write_cb;
grpc_closure on_read;
grpc_closure on_write;
grpc_closure *read_cb;
grpc_closure *write_cb;
gpr_slice read_slice;
gpr_slice_buffer *write_slices;
gpr_slice_buffer *read_slices;
@ -108,18 +111,18 @@ static void tcp_free(grpc_tcp *tcp) {
#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__)
#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__)
static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file,
int line) {
int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp,
reason, tcp->refcount.count, tcp->refcount.count - 1);
reason, tcp->refcount.count, tcp->refcount.count - 1);
if (gpr_unref(&tcp->refcount)) {
tcp_free(tcp);
}
}
static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file,
int line) {
int line) {
gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp,
reason, tcp->refcount.count, tcp->refcount.count + 1);
reason, tcp->refcount.count, tcp->refcount.count + 1);
gpr_ref(&tcp->refcount);
}
#else
@ -135,7 +138,9 @@ static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); }
#endif
/* Asynchronous callback from the IOCP, or the background thread. */
static int on_read(grpc_tcp *tcp, int success) {
static void on_read(grpc_exec_ctx *exec_ctx, void *tcpp, int success) {
grpc_tcp *tcp = tcpp;
grpc_closure *cb = tcp->read_cb;
grpc_winsocket *socket = tcp->socket;
gpr_slice sub;
gpr_slice *slice = NULL;
@ -164,23 +169,15 @@ static int on_read(grpc_tcp *tcp, int success) {
}
}
return success;
}
static void on_read_cb(void *tcpp, int from_iocp) {
grpc_tcp *tcp = tcpp;
grpc_iomgr_closure *cb = tcp->read_cb;
int success = on_read(tcp, from_iocp);
tcp->read_cb = NULL;
TCP_UNREF(tcp, "read");
if (cb) {
cb->cb(cb->cb_arg, success);
cb->cb(exec_ctx, cb->cb_arg, success);
}
}
static grpc_endpoint_op_status win_read(grpc_endpoint *ep,
gpr_slice_buffer *read_slices,
grpc_iomgr_closure *cb) {
static void win_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *read_slices, grpc_closure *cb) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_winsocket *handle = tcp->socket;
grpc_winsocket_callback_info *info = &handle->read_info;
@ -190,7 +187,8 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep,
WSABUF buffer;
if (tcp->shutting_down) {
return GRPC_ENDPOINT_ERROR;
grpc_exec_ctx_enqueue(exec_ctx, cb, 0);
return;
}
tcp->read_cb = cb;
@ -202,6 +200,8 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep,
buffer.len = GPR_SLICE_LENGTH(tcp->read_slice);
buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice);
TCP_REF(tcp, "read");
/* First let's try a synchronous, non-blocking read. */
status =
WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, NULL, NULL);
@ -209,14 +209,11 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep,
/* Did we get data immediately ? Yay. */
if (info->wsa_error != WSAEWOULDBLOCK) {
int ok;
info->bytes_transfered = bytes_read;
ok = on_read(tcp, 1);
return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR;
grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, 1);
return;
}
TCP_REF(tcp, "read");
/* Otherwise, let's retry, by queuing a read. */
memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED));
status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags,
@ -225,23 +222,21 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep,
if (status != 0) {
int wsa_error = WSAGetLastError();
if (wsa_error != WSA_IO_PENDING) {
int ok;
info->wsa_error = wsa_error;
ok = on_read(tcp, 1);
return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR;
grpc_exec_ctx_enqueue(exec_ctx, &tcp->on_read, 0);
return;
}
}
grpc_socket_notify_on_read(tcp->socket, on_read_cb, tcp);
return GRPC_ENDPOINT_PENDING;
grpc_socket_notify_on_read(exec_ctx, tcp->socket, &tcp->on_read);
}
/* Asynchronous callback from the IOCP, or the background thread. */
static void on_write(void *tcpp, int success) {
static void on_write(grpc_exec_ctx *exec_ctx, void *tcpp, int success) {
grpc_tcp *tcp = (grpc_tcp *)tcpp;
grpc_winsocket *handle = tcp->socket;
grpc_winsocket_callback_info *info = &handle->write_info;
grpc_iomgr_closure *cb;
grpc_closure *cb;
int do_abort = 0;
gpr_mu_lock(&tcp->mu);
@ -263,13 +258,12 @@ static void on_write(void *tcpp, int success) {
}
TCP_UNREF(tcp, "write");
cb->cb(cb->cb_arg, success);
cb->cb(exec_ctx, cb->cb_arg, success);
}
/* Initiates a write. */
static grpc_endpoint_op_status win_write(grpc_endpoint *ep,
gpr_slice_buffer *slices,
grpc_iomgr_closure *cb) {
static void win_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
gpr_slice_buffer *slices, grpc_closure *cb) {
grpc_tcp *tcp = (grpc_tcp *)ep;
grpc_winsocket *socket = tcp->socket;
grpc_winsocket_callback_info *info = &socket->write_info;
@ -281,7 +275,8 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep,
WSABUF *buffers = local_buffers;
if (tcp->shutting_down) {
return GRPC_ENDPOINT_ERROR;
grpc_exec_ctx_enqueue(exec_ctx, cb, 0);
return;
}
tcp->write_cb = cb;
@ -306,9 +301,9 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep,
connection that has its send queue filled up. But if we don't, then we can
avoid doing an async write operation at all. */
if (info->wsa_error != WSAEWOULDBLOCK) {
grpc_endpoint_op_status ret = GRPC_ENDPOINT_ERROR;
int ok = 0;
if (status == 0) {
ret = GRPC_ENDPOINT_DONE;
ok = 1;
GPR_ASSERT(bytes_sent == tcp->write_slices->length);
} else {
if (socket->read_info.wsa_error != WSAECONNRESET) {
@ -318,7 +313,8 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep,
}
}
if (allocated) gpr_free(allocated);
return ret;
grpc_exec_ctx_enqueue(exec_ctx, cb, ok);
return;
}
TCP_REF(tcp, "write");
@ -334,24 +330,26 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep,
int wsa_error = WSAGetLastError();
if (wsa_error != WSA_IO_PENDING) {
TCP_UNREF(tcp, "write");
return GRPC_ENDPOINT_ERROR;
grpc_exec_ctx_enqueue(exec_ctx, cb, 0);
return;
}
}
/* As all is now setup, we can now ask for the IOCP notification. It may
trigger the callback immediately however, but no matter. */
grpc_socket_notify_on_write(socket, on_write, tcp);
return GRPC_ENDPOINT_PENDING;
grpc_socket_notify_on_write(exec_ctx, socket, &tcp->on_write);
}
static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) {
static void win_add_to_pollset(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset *ps) {
grpc_tcp *tcp;
(void)ps;
tcp = (grpc_tcp *)ep;
grpc_iocp_add_socket(tcp->socket);
}
static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) {
static void win_add_to_pollset_set(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep,
grpc_pollset_set *pss) {
grpc_tcp *tcp;
(void)pss;
tcp = (grpc_tcp *)ep;
@ -364,7 +362,7 @@ static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) {
we're not going to protect against these. However the IO Completion Port
callback will happen from another thread, so we need to protect against
concurrent access of the data structure in that regard. */
static void win_shutdown(grpc_endpoint *ep) {
static void win_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
gpr_mu_lock(&tcp->mu);
/* At that point, what may happen is that we're already inside the IOCP
@ -374,7 +372,7 @@ static void win_shutdown(grpc_endpoint *ep) {
gpr_mu_unlock(&tcp->mu);
}
static void win_destroy(grpc_endpoint *ep) {
static void win_destroy(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep) {
grpc_tcp *tcp = (grpc_tcp *)ep;
TCP_UNREF(tcp, "destroy");
}
@ -395,6 +393,8 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) {
tcp->socket = socket;
gpr_mu_init(&tcp->mu);
gpr_ref_init(&tcp->refcount, 1);
grpc_closure_init(&tcp->on_read, on_read, tcp);
grpc_closure_init(&tcp->on_write, on_write, tcp);
tcp->peer_string = gpr_strdup(peer_string);
return &tcp->base;
}

@ -33,7 +33,7 @@
#include "src/core/iomgr/time_averaged_stats.h"
void grpc_time_averaged_stats_init(grpc_time_averaged_stats *stats,
void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
double init_avg, double regress_weight,
double persistence_factor) {
stats->init_avg = init_avg;
@ -45,14 +45,14 @@ void grpc_time_averaged_stats_init(grpc_time_averaged_stats *stats,
stats->aggregate_weighted_avg = init_avg;
}
void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats *stats,
void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats,
double value) {
stats->batch_total_value += value;
++stats->batch_num_samples;
}
double grpc_time_averaged_stats_update_average(
grpc_time_averaged_stats *stats) {
grpc_time_averaged_stats* stats) {
/* Start with the current batch: */
double weighted_sum = stats->batch_total_value;
double total_weight = stats->batch_num_samples;

@ -75,14 +75,14 @@ typedef struct {
/* See the comments on the members above for an explanation of init_avg,
regress_weight, and persistence_factor. */
void grpc_time_averaged_stats_init(grpc_time_averaged_stats *stats,
void grpc_time_averaged_stats_init(grpc_time_averaged_stats* stats,
double init_avg, double regress_weight,
double persistence_factor);
/* Add a sample to the current batch. */
void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats *stats,
void grpc_time_averaged_stats_add_sample(grpc_time_averaged_stats* stats,
double value);
/* Complete a batch and compute the new estimate of the average sample
value. */
double grpc_time_averaged_stats_update_average(grpc_time_averaged_stats *stats);
double grpc_time_averaged_stats_update_average(grpc_time_averaged_stats* stats);
#endif /* GRPC_INTERNAL_CORE_IOMGR_TIME_AVERAGED_STATS_H */

@ -79,8 +79,8 @@ typedef struct {
struct sockaddr_un un;
} addr;
size_t addr_len;
grpc_iomgr_closure read_closure;
grpc_iomgr_closure destroyed_closure;
grpc_closure read_closure;
grpc_closure destroyed_closure;
grpc_udp_server_read_cb read_cb;
} server_port;
@ -111,8 +111,7 @@ struct grpc_udp_server {
size_t port_capacity;
/* shutdown callback */
void (*shutdown_complete)(void *);
void *shutdown_complete_arg;
grpc_closure *shutdown_complete;
/* all pollsets interested in new connections */
grpc_pollset **pollsets;
@ -134,8 +133,8 @@ grpc_udp_server *grpc_udp_server_create(void) {
return s;
}
static void finish_shutdown(grpc_udp_server *s) {
s->shutdown_complete(s->shutdown_complete_arg);
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1);
gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
@ -144,24 +143,22 @@ static void finish_shutdown(grpc_udp_server *s) {
gpr_free(s);
}
static void destroyed_port(void *server, int success) {
static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, int success) {
grpc_udp_server *s = server;
gpr_mu_lock(&s->mu);
s->destroyed_ports++;
if (s->destroyed_ports == s->nports) {
gpr_mu_unlock(&s->mu);
finish_shutdown(s);
finish_shutdown(exec_ctx, s);
} else {
gpr_mu_unlock(&s->mu);
}
}
static void dont_care_about_shutdown_completion(void *ignored) {}
/* called when all listening endpoints have been shutdown, so no further
events will be received on them - at this point it's safe to destroy
things */
static void deactivated_all_ports(grpc_udp_server *s) {
static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
size_t i;
/* delete ALL the things */
@ -180,38 +177,35 @@ static void deactivated_all_ports(grpc_udp_server *s) {
}
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
grpc_fd_orphan(sp->emfd, &sp->destroyed_closure, "udp_listener_shutdown");
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
"udp_listener_shutdown");
}
gpr_mu_unlock(&s->mu);
} else {
gpr_mu_unlock(&s->mu);
finish_shutdown(s);
finish_shutdown(exec_ctx, s);
}
}
void grpc_udp_server_destroy(
grpc_udp_server *s, void (*shutdown_complete)(void *shutdown_complete_arg),
void *shutdown_complete_arg) {
void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
grpc_closure *on_done) {
size_t i;
gpr_mu_lock(&s->mu);
GPR_ASSERT(!s->shutdown);
s->shutdown = 1;
s->shutdown_complete = shutdown_complete
? shutdown_complete
: dont_care_about_shutdown_completion;
s->shutdown_complete_arg = shutdown_complete_arg;
s->shutdown_complete = on_done;
/* shutdown all fd's */
if (s->active_ports) {
for (i = 0; i < s->nports; i++) {
grpc_fd_shutdown(s->ports[i].emfd);
grpc_fd_shutdown(exec_ctx, s->ports[i].emfd);
}
gpr_mu_unlock(&s->mu);
} else {
gpr_mu_unlock(&s->mu);
deactivated_all_ports(s);
deactivated_all_ports(exec_ctx, s);
}
}
@ -266,14 +260,14 @@ error:
}
/* event manager callback when reads are ready */
static void on_read(void *arg, int success) {
static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
server_port *sp = arg;
if (success == 0) {
gpr_mu_lock(&sp->server->mu);
if (0 == --sp->server->active_ports) {
gpr_mu_unlock(&sp->server->mu);
deactivated_all_ports(sp->server);
deactivated_all_ports(exec_ctx, sp->server);
} else {
gpr_mu_unlock(&sp->server->mu);
}
@ -285,7 +279,7 @@ static void on_read(void *arg, int success) {
sp->read_cb(sp->fd);
/* Re-arm the notification event so we get another chance to read. */
grpc_fd_notify_on_read(sp->emfd, &sp->read_closure);
grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
}
static int add_socket_to_server(grpc_udp_server *s, int fd,
@ -300,6 +294,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
if (port >= 0) {
grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
gpr_asprintf(&name, "udp-server-listener:%s", addr_str);
gpr_free(addr_str);
gpr_mu_lock(&s->mu);
/* append it to the list under a lock */
if (s->nports == s->port_capacity) {
@ -315,6 +310,7 @@ static int add_socket_to_server(grpc_udp_server *s, int fd,
sp->read_cb = read_cb;
GPR_ASSERT(sp->emfd);
gpr_mu_unlock(&s->mu);
gpr_free(name);
}
return port;
@ -405,19 +401,20 @@ int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index) {
return (index < s->nports) ? s->ports[index].fd : -1;
}
void grpc_udp_server_start(grpc_udp_server *s, grpc_pollset **pollsets,
size_t pollset_count) {
void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *s,
grpc_pollset **pollsets, size_t pollset_count) {
size_t i, j;
gpr_mu_lock(&s->mu);
GPR_ASSERT(s->active_ports == 0);
s->pollsets = pollsets;
for (i = 0; i < s->nports; i++) {
for (j = 0; j < pollset_count; j++) {
grpc_pollset_add_fd(pollsets[j], s->ports[i].emfd);
grpc_pollset_add_fd(exec_ctx, pollsets[j], s->ports[i].emfd);
}
s->ports[i].read_closure.cb = on_read;
s->ports[i].read_closure.cb_arg = &s->ports[i];
grpc_fd_notify_on_read(s->ports[i].emfd, &s->ports[i].read_closure);
grpc_fd_notify_on_read(exec_ctx, s->ports[i].emfd,
&s->ports[i].read_closure);
s->active_ports++;
}
gpr_mu_unlock(&s->mu);

@ -46,8 +46,8 @@ typedef void (*grpc_udp_server_read_cb)(int fd);
grpc_udp_server *grpc_udp_server_create(void);
/* Start listening to bound ports */
void grpc_udp_server_start(grpc_udp_server *udp_server, grpc_pollset **pollsets,
size_t pollset_count);
void grpc_udp_server_start(grpc_exec_ctx *exec_ctx, grpc_udp_server *udp_server,
grpc_pollset **pollsets, size_t pollset_count);
int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index);
@ -64,9 +64,8 @@ int grpc_udp_server_get_fd(grpc_udp_server *s, unsigned index);
int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
size_t addr_len, grpc_udp_server_read_cb read_cb);
void grpc_udp_server_destroy(grpc_udp_server *server,
void (*shutdown_done)(void *shutdown_done_arg),
void *shutdown_done_arg);
void grpc_udp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_udp_server *server,
grpc_closure *on_done);
/* Write the contents of buffer to the underlying UDP socket. */
/*

@ -42,7 +42,7 @@
#include "src/core/iomgr/wakeup_fd_posix.h"
#include <grpc/support/log.h>
static void eventfd_create(grpc_wakeup_fd *fd_info) {
static void eventfd_create(grpc_wakeup_fd* fd_info) {
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
/* TODO(klempner): Handle failure more gracefully */
GPR_ASSERT(efd >= 0);
@ -50,7 +50,7 @@ static void eventfd_create(grpc_wakeup_fd *fd_info) {
fd_info->write_fd = -1;
}
static void eventfd_consume(grpc_wakeup_fd *fd_info) {
static void eventfd_consume(grpc_wakeup_fd* fd_info) {
eventfd_t value;
int err;
do {
@ -58,15 +58,15 @@ static void eventfd_consume(grpc_wakeup_fd *fd_info) {
} while (err < 0 && errno == EINTR);
}
static void eventfd_wakeup(grpc_wakeup_fd *fd_info) {
static void eventfd_wakeup(grpc_wakeup_fd* fd_info) {
int err;
do {
err = eventfd_write(fd_info->read_fd, 1);
} while (err < 0 && errno == EINTR);
}
static void eventfd_destroy(grpc_wakeup_fd *fd_info) {
close(fd_info->read_fd);
static void eventfd_destroy(grpc_wakeup_fd* fd_info) {
if (fd_info->read_fd != 0) close(fd_info->read_fd);
}
static int eventfd_check_availability(void) {

@ -44,7 +44,7 @@
#include "src/core/iomgr/socket_utils_posix.h"
#include <grpc/support/log.h>
static void pipe_init(grpc_wakeup_fd *fd_info) {
static void pipe_init(grpc_wakeup_fd* fd_info) {
int pipefd[2];
/* TODO(klempner): Make this nonfatal */
GPR_ASSERT(0 == pipe(pipefd));
@ -54,7 +54,7 @@ static void pipe_init(grpc_wakeup_fd *fd_info) {
fd_info->write_fd = pipefd[1];
}
static void pipe_consume(grpc_wakeup_fd *fd_info) {
static void pipe_consume(grpc_wakeup_fd* fd_info) {
char buf[128];
ssize_t r;
@ -74,15 +74,15 @@ static void pipe_consume(grpc_wakeup_fd *fd_info) {
}
}
static void pipe_wakeup(grpc_wakeup_fd *fd_info) {
static void pipe_wakeup(grpc_wakeup_fd* fd_info) {
char c = 0;
while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR)
;
}
static void pipe_destroy(grpc_wakeup_fd *fd_info) {
close(fd_info->read_fd);
close(fd_info->write_fd);
static void pipe_destroy(grpc_wakeup_fd* fd_info) {
if (fd_info->read_fd != 0) close(fd_info->read_fd);
if (fd_info->write_fd != 0) close(fd_info->write_fd);
}
static int pipe_check_availability(void) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save