Merge github.com:grpc/grpc into hansel

pull/8775/head
Craig Tiller 8 years ago
commit 4b064060f7
  1. 2
      .gitignore
  2. 341
      BUILD
  3. 189
      CMakeLists.txt
  4. 239
      Makefile
  5. 2
      binding.gyp
  6. 20
      build.yaml
  7. 2
      config.m4
  8. 11
      examples/csharp/helloworld-from-cli/Greeter/project.json
  9. 11
      examples/csharp/helloworld-from-cli/GreeterClient/project.json
  10. 11
      examples/csharp/helloworld-from-cli/GreeterServer/project.json
  11. 8
      examples/csharp/helloworld/Greeter/Greeter.csproj
  12. 6
      examples/csharp/helloworld/Greeter/packages.config
  13. 8
      examples/csharp/helloworld/GreeterClient/GreeterClient.csproj
  14. 4
      examples/csharp/helloworld/GreeterClient/packages.config
  15. 8
      examples/csharp/helloworld/GreeterServer/GreeterServer.csproj
  16. 4
      examples/csharp/helloworld/GreeterServer/packages.config
  17. 88
      examples/csharp/route_guide/RouteGuide/RouteGuide.cs
  18. 8
      examples/csharp/route_guide/RouteGuide/RouteGuide.csproj
  19. 4
      examples/csharp/route_guide/RouteGuide/packages.config
  20. 8
      examples/csharp/route_guide/RouteGuideClient/RouteGuideClient.csproj
  21. 4
      examples/csharp/route_guide/RouteGuideClient/packages.config
  22. 8
      examples/csharp/route_guide/RouteGuideServer/RouteGuideServer.csproj
  23. 6
      examples/csharp/route_guide/RouteGuideServer/packages.config
  24. 6
      gRPC-Core.podspec
  25. 1
      grpc.def
  26. 5
      grpc.gemspec
  27. 7
      include/grpc++/channel.h
  28. 13
      include/grpc++/support/channel_arguments.h
  29. 8
      include/grpc/impl/codegen/grpc_types.h
  30. 4
      include/grpc/slice.h
  31. 4
      package.xml
  32. 8
      src/compiler/csharp_generator.cc
  33. 120
      src/core/ext/client_channel/client_channel.c
  34. 8
      src/core/ext/client_channel/lb_policy_registry.c
  35. 138
      src/core/ext/client_channel/subchannel.c
  36. 209
      src/core/ext/lb_policy/grpclb/grpclb.c
  37. 16
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  38. 66
      src/core/lib/channel/http_client_filter.c
  39. 28
      src/core/lib/channel/http_server_filter.c
  40. 77
      src/core/lib/channel/message_size_filter.c
  41. 31
      src/core/lib/iomgr/ev_epoll_linux.c
  42. 29
      src/core/lib/iomgr/ev_poll_posix.c
  43. 1
      src/core/lib/iomgr/ev_posix.h
  44. 1
      src/core/lib/iomgr/iomgr.c
  45. 30
      src/core/lib/iomgr/resource_quota.c
  46. 8
      src/core/lib/iomgr/socket_windows.c
  47. 1
      src/core/lib/iomgr/socket_windows.h
  48. 7
      src/core/lib/iomgr/tcp_client_posix.c
  49. 26
      src/core/lib/iomgr/tcp_client_windows.c
  50. 86
      src/core/lib/iomgr/tcp_server_windows.c
  51. 2
      src/core/lib/iomgr/tcp_windows.c
  52. 6
      src/core/lib/json/json.c
  53. 22
      src/core/lib/json/json.h
  54. 8
      src/core/lib/slice/slice.c
  55. 9
      src/core/lib/support/string.c
  56. 3
      src/core/lib/support/string.h
  57. 7
      src/core/lib/support/subprocess_posix.c
  58. 5
      src/core/lib/surface/call.c
  59. 11
      src/core/lib/surface/server.c
  60. 13
      src/core/lib/transport/connectivity_state.c
  61. 5
      src/core/lib/transport/connectivity_state.h
  62. 42
      src/core/lib/transport/mdstr_hash_table.c
  63. 18
      src/core/lib/transport/mdstr_hash_table.h
  64. 340
      src/core/lib/transport/method_config.c
  65. 136
      src/core/lib/transport/method_config.h
  66. 249
      src/core/lib/transport/service_config.c
  67. 70
      src/core/lib/transport/service_config.h
  68. 30
      src/cpp/client/channel_cc.cc
  69. 5
      src/cpp/common/channel_arguments.cc
  70. 1
      src/csharp/Grpc.Auth/project.json
  71. 6
      src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
  72. 3
      src/csharp/Grpc.Core.Tests/SanityTest.cs
  73. 4
      src/csharp/Grpc.Core.Tests/packages.config
  74. 2
      src/csharp/Grpc.Core.Tests/project.json
  75. 2
      src/csharp/Grpc.Core/Grpc.Core.csproj
  76. 2
      src/csharp/Grpc.Core/Grpc.Core.nuspec
  77. 2
      src/csharp/Grpc.Core/packages.config
  78. 3
      src/csharp/Grpc.Core/project.json
  79. 14
      src/csharp/Grpc.Dotnet.sln
  80. 2
      src/csharp/Grpc.Examples.MathClient/project.json
  81. 2
      src/csharp/Grpc.Examples.MathServer/project.json
  82. 6
      src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
  83. 2
      src/csharp/Grpc.Examples.Tests/packages.config
  84. 2
      src/csharp/Grpc.Examples.Tests/project.json
  85. 7
      src/csharp/Grpc.Examples/Grpc.Examples.csproj
  86. 24
      src/csharp/Grpc.Examples/Math.cs
  87. 8
      src/csharp/Grpc.Examples/MathGrpc.cs
  88. 2
      src/csharp/Grpc.Examples/packages.config
  89. 2
      src/csharp/Grpc.HealthCheck.Tests/project.json
  90. 7
      src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
  91. 2
      src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
  92. 22
      src/csharp/Grpc.HealthCheck/Health.cs
  93. 8
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  94. 2
      src/csharp/Grpc.HealthCheck/packages.config
  95. 1
      src/csharp/Grpc.HealthCheck/project.json
  96. 2
      src/csharp/Grpc.IntegrationTesting.Client/project.json
  97. 2
      src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
  98. 2
      src/csharp/Grpc.IntegrationTesting.Server/project.json
  99. 2
      src/csharp/Grpc.IntegrationTesting.StressClient/project.json
  100. 220
      src/csharp/Grpc.IntegrationTesting/Control.cs
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -17,7 +17,7 @@ py27/
py34/ py34/
# Node installation output # Node installation output
^node_modules node_modules
src/node/extension_binary/ src/node/extension_binary/
# gcov coverage data # gcov coverage data

341
BUILD

@ -247,8 +247,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -436,8 +436,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -681,8 +681,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -855,8 +855,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -1070,8 +1070,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",
@ -1236,8 +1236,8 @@ cc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -1515,6 +1515,150 @@ cc_library(
"src/cpp/server/dynamic_thread_pool.h", "src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h", "src/cpp/server/thread_pool_interface.h",
"src/cpp/thread_manager/thread_manager.h", "src/cpp/thread_manager/thread_manager.h",
"src/core/ext/transport/chttp2/transport/bin_decoder.h",
"src/core/ext/transport/chttp2/transport/bin_encoder.h",
"src/core/ext/transport/chttp2/transport/chttp2_transport.h",
"src/core/ext/transport/chttp2/transport/frame.h",
"src/core/ext/transport/chttp2/transport/frame_data.h",
"src/core/ext/transport/chttp2/transport/frame_goaway.h",
"src/core/ext/transport/chttp2/transport/frame_ping.h",
"src/core/ext/transport/chttp2/transport/frame_rst_stream.h",
"src/core/ext/transport/chttp2/transport/frame_settings.h",
"src/core/ext/transport/chttp2/transport/frame_window_update.h",
"src/core/ext/transport/chttp2/transport/hpack_encoder.h",
"src/core/ext/transport/chttp2/transport/hpack_parser.h",
"src/core/ext/transport/chttp2/transport/hpack_table.h",
"src/core/ext/transport/chttp2/transport/http2_errors.h",
"src/core/ext/transport/chttp2/transport/huffsyms.h",
"src/core/ext/transport/chttp2/transport/incoming_metadata.h",
"src/core/ext/transport/chttp2/transport/internal.h",
"src/core/ext/transport/chttp2/transport/status_conversion.h",
"src/core/ext/transport/chttp2/transport/stream_map.h",
"src/core/ext/transport/chttp2/transport/varint.h",
"src/core/lib/channel/channel_args.h",
"src/core/lib/channel/channel_stack.h",
"src/core/lib/channel/channel_stack_builder.h",
"src/core/lib/channel/compress_filter.h",
"src/core/lib/channel/connected_channel.h",
"src/core/lib/channel/context.h",
"src/core/lib/channel/deadline_filter.h",
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
"src/core/lib/http/format_request.h",
"src/core/lib/http/httpcli.h",
"src/core/lib/http/parser.h",
"src/core/lib/iomgr/closure.h",
"src/core/lib/iomgr/combiner.h",
"src/core/lib/iomgr/endpoint.h",
"src/core/lib/iomgr/endpoint_pair.h",
"src/core/lib/iomgr/error.h",
"src/core/lib/iomgr/ev_epoll_linux.h",
"src/core/lib/iomgr/ev_poll_posix.h",
"src/core/lib/iomgr/ev_posix.h",
"src/core/lib/iomgr/exec_ctx.h",
"src/core/lib/iomgr/executor.h",
"src/core/lib/iomgr/iocp_windows.h",
"src/core/lib/iomgr/iomgr.h",
"src/core/lib/iomgr/iomgr_internal.h",
"src/core/lib/iomgr/iomgr_posix.h",
"src/core/lib/iomgr/load_file.h",
"src/core/lib/iomgr/network_status_tracker.h",
"src/core/lib/iomgr/polling_entity.h",
"src/core/lib/iomgr/pollset.h",
"src/core/lib/iomgr/pollset_set.h",
"src/core/lib/iomgr/pollset_set_windows.h",
"src/core/lib/iomgr/pollset_uv.h",
"src/core/lib/iomgr/pollset_windows.h",
"src/core/lib/iomgr/port.h",
"src/core/lib/iomgr/resolve_address.h",
"src/core/lib/iomgr/resource_quota.h",
"src/core/lib/iomgr/sockaddr.h",
"src/core/lib/iomgr/sockaddr_posix.h",
"src/core/lib/iomgr/sockaddr_utils.h",
"src/core/lib/iomgr/sockaddr_windows.h",
"src/core/lib/iomgr/socket_mutator.h",
"src/core/lib/iomgr/socket_utils.h",
"src/core/lib/iomgr/socket_utils_posix.h",
"src/core/lib/iomgr/socket_windows.h",
"src/core/lib/iomgr/tcp_client.h",
"src/core/lib/iomgr/tcp_client_posix.h",
"src/core/lib/iomgr/tcp_posix.h",
"src/core/lib/iomgr/tcp_server.h",
"src/core/lib/iomgr/tcp_uv.h",
"src/core/lib/iomgr/tcp_windows.h",
"src/core/lib/iomgr/time_averaged_stats.h",
"src/core/lib/iomgr/timer.h",
"src/core/lib/iomgr/timer_generic.h",
"src/core/lib/iomgr/timer_heap.h",
"src/core/lib/iomgr/timer_uv.h",
"src/core/lib/iomgr/udp_server.h",
"src/core/lib/iomgr/unix_sockets_posix.h",
"src/core/lib/iomgr/wakeup_fd_cv.h",
"src/core/lib/iomgr/wakeup_fd_pipe.h",
"src/core/lib/iomgr/wakeup_fd_posix.h",
"src/core/lib/iomgr/workqueue.h",
"src/core/lib/iomgr/workqueue_uv.h",
"src/core/lib/iomgr/workqueue_windows.h",
"src/core/lib/json/json.h",
"src/core/lib/json/json_common.h",
"src/core/lib/json/json_reader.h",
"src/core/lib/json/json_writer.h",
"src/core/lib/slice/percent_encoding.h",
"src/core/lib/slice/slice_string_helpers.h",
"src/core/lib/surface/api_trace.h",
"src/core/lib/surface/call.h",
"src/core/lib/surface/call_test_only.h",
"src/core/lib/surface/channel.h",
"src/core/lib/surface/channel_init.h",
"src/core/lib/surface/channel_stack_type.h",
"src/core/lib/surface/completion_queue.h",
"src/core/lib/surface/event_string.h",
"src/core/lib/surface/init.h",
"src/core/lib/surface/lame_client.h",
"src/core/lib/surface/server.h",
"src/core/lib/transport/byte_stream.h",
"src/core/lib/transport/connectivity_state.h",
"src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h",
"src/core/lib/transport/transport_impl.h",
"src/core/ext/transport/chttp2/alpn/alpn.h",
"src/core/ext/client_channel/client_channel.h",
"src/core/ext/client_channel/client_channel_factory.h",
"src/core/ext/client_channel/connector.h",
"src/core/ext/client_channel/http_connect_handshaker.h",
"src/core/ext/client_channel/initial_connect_string.h",
"src/core/ext/client_channel/lb_policy.h",
"src/core/ext/client_channel/lb_policy_factory.h",
"src/core/ext/client_channel/lb_policy_registry.h",
"src/core/ext/client_channel/parse_address.h",
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h",
"src/core/ext/census/aggregation.h",
"src/core/ext/census/base_resources.h",
"src/core/ext/census/census_interface.h",
"src/core/ext/census/census_rpc_stats.h",
"src/core/ext/census/gen/census.pb.h",
"src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.h",
"src/cpp/client/cronet_credentials.cc", "src/cpp/client/cronet_credentials.cc",
"src/cpp/client/insecure_credentials.cc", "src/cpp/client/insecure_credentials.cc",
"src/cpp/common/insecure_create_auth_context.cc", "src/cpp/common/insecure_create_auth_context.cc",
@ -1548,6 +1692,176 @@ cc_library(
"src/cpp/util/string_ref.cc", "src/cpp/util/string_ref.cc",
"src/cpp/util/time_cc.cc", "src/cpp/util/time_cc.cc",
"src/cpp/codegen/codegen_init.cc", "src/cpp/codegen/codegen_init.cc",
"src/core/ext/transport/chttp2/client/insecure/channel_create.c",
"src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c",
"src/core/ext/transport/chttp2/transport/bin_decoder.c",
"src/core/ext/transport/chttp2/transport/bin_encoder.c",
"src/core/ext/transport/chttp2/transport/chttp2_plugin.c",
"src/core/ext/transport/chttp2/transport/chttp2_transport.c",
"src/core/ext/transport/chttp2/transport/frame_data.c",
"src/core/ext/transport/chttp2/transport/frame_goaway.c",
"src/core/ext/transport/chttp2/transport/frame_ping.c",
"src/core/ext/transport/chttp2/transport/frame_rst_stream.c",
"src/core/ext/transport/chttp2/transport/frame_settings.c",
"src/core/ext/transport/chttp2/transport/frame_window_update.c",
"src/core/ext/transport/chttp2/transport/hpack_encoder.c",
"src/core/ext/transport/chttp2/transport/hpack_parser.c",
"src/core/ext/transport/chttp2/transport/hpack_table.c",
"src/core/ext/transport/chttp2/transport/huffsyms.c",
"src/core/ext/transport/chttp2/transport/incoming_metadata.c",
"src/core/ext/transport/chttp2/transport/parsing.c",
"src/core/ext/transport/chttp2/transport/status_conversion.c",
"src/core/ext/transport/chttp2/transport/stream_lists.c",
"src/core/ext/transport/chttp2/transport/stream_map.c",
"src/core/ext/transport/chttp2/transport/varint.c",
"src/core/ext/transport/chttp2/transport/writing.c",
"src/core/lib/channel/channel_args.c",
"src/core/lib/channel/channel_stack.c",
"src/core/lib/channel/channel_stack_builder.c",
"src/core/lib/channel/compress_filter.c",
"src/core/lib/channel/connected_channel.c",
"src/core/lib/channel/deadline_filter.c",
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
"src/core/lib/http/format_request.c",
"src/core/lib/http/httpcli.c",
"src/core/lib/http/parser.c",
"src/core/lib/iomgr/closure.c",
"src/core/lib/iomgr/combiner.c",
"src/core/lib/iomgr/endpoint.c",
"src/core/lib/iomgr/endpoint_pair_posix.c",
"src/core/lib/iomgr/endpoint_pair_uv.c",
"src/core/lib/iomgr/endpoint_pair_windows.c",
"src/core/lib/iomgr/error.c",
"src/core/lib/iomgr/ev_epoll_linux.c",
"src/core/lib/iomgr/ev_poll_posix.c",
"src/core/lib/iomgr/ev_posix.c",
"src/core/lib/iomgr/exec_ctx.c",
"src/core/lib/iomgr/executor.c",
"src/core/lib/iomgr/iocp_windows.c",
"src/core/lib/iomgr/iomgr.c",
"src/core/lib/iomgr/iomgr_posix.c",
"src/core/lib/iomgr/iomgr_uv.c",
"src/core/lib/iomgr/iomgr_windows.c",
"src/core/lib/iomgr/load_file.c",
"src/core/lib/iomgr/network_status_tracker.c",
"src/core/lib/iomgr/polling_entity.c",
"src/core/lib/iomgr/pollset_set_uv.c",
"src/core/lib/iomgr/pollset_set_windows.c",
"src/core/lib/iomgr/pollset_uv.c",
"src/core/lib/iomgr/pollset_windows.c",
"src/core/lib/iomgr/resolve_address_posix.c",
"src/core/lib/iomgr/resolve_address_uv.c",
"src/core/lib/iomgr/resolve_address_windows.c",
"src/core/lib/iomgr/resource_quota.c",
"src/core/lib/iomgr/sockaddr_utils.c",
"src/core/lib/iomgr/socket_mutator.c",
"src/core/lib/iomgr/socket_utils_common_posix.c",
"src/core/lib/iomgr/socket_utils_linux.c",
"src/core/lib/iomgr/socket_utils_posix.c",
"src/core/lib/iomgr/socket_utils_uv.c",
"src/core/lib/iomgr/socket_utils_windows.c",
"src/core/lib/iomgr/socket_windows.c",
"src/core/lib/iomgr/tcp_client_posix.c",
"src/core/lib/iomgr/tcp_client_uv.c",
"src/core/lib/iomgr/tcp_client_windows.c",
"src/core/lib/iomgr/tcp_posix.c",
"src/core/lib/iomgr/tcp_server_posix.c",
"src/core/lib/iomgr/tcp_server_uv.c",
"src/core/lib/iomgr/tcp_server_windows.c",
"src/core/lib/iomgr/tcp_uv.c",
"src/core/lib/iomgr/tcp_windows.c",
"src/core/lib/iomgr/time_averaged_stats.c",
"src/core/lib/iomgr/timer_generic.c",
"src/core/lib/iomgr/timer_heap.c",
"src/core/lib/iomgr/timer_uv.c",
"src/core/lib/iomgr/udp_server.c",
"src/core/lib/iomgr/unix_sockets_posix.c",
"src/core/lib/iomgr/unix_sockets_posix_noop.c",
"src/core/lib/iomgr/wakeup_fd_cv.c",
"src/core/lib/iomgr/wakeup_fd_eventfd.c",
"src/core/lib/iomgr/wakeup_fd_nospecial.c",
"src/core/lib/iomgr/wakeup_fd_pipe.c",
"src/core/lib/iomgr/wakeup_fd_posix.c",
"src/core/lib/iomgr/workqueue_uv.c",
"src/core/lib/iomgr/workqueue_windows.c",
"src/core/lib/json/json.c",
"src/core/lib/json/json_reader.c",
"src/core/lib/json/json_string.c",
"src/core/lib/json/json_writer.c",
"src/core/lib/slice/percent_encoding.c",
"src/core/lib/slice/slice.c",
"src/core/lib/slice/slice_buffer.c",
"src/core/lib/slice/slice_string_helpers.c",
"src/core/lib/surface/alarm.c",
"src/core/lib/surface/api_trace.c",
"src/core/lib/surface/byte_buffer.c",
"src/core/lib/surface/byte_buffer_reader.c",
"src/core/lib/surface/call.c",
"src/core/lib/surface/call_details.c",
"src/core/lib/surface/call_log_batch.c",
"src/core/lib/surface/channel.c",
"src/core/lib/surface/channel_init.c",
"src/core/lib/surface/channel_ping.c",
"src/core/lib/surface/channel_stack_type.c",
"src/core/lib/surface/completion_queue.c",
"src/core/lib/surface/event_string.c",
"src/core/lib/surface/lame_client.c",
"src/core/lib/surface/metadata_array.c",
"src/core/lib/surface/server.c",
"src/core/lib/surface/validate_metadata.c",
"src/core/lib/surface/version.c",
"src/core/lib/transport/byte_stream.c",
"src/core/lib/transport/connectivity_state.c",
"src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c",
"src/core/lib/transport/transport_op_string.c",
"src/core/ext/transport/chttp2/alpn/alpn.c",
"src/core/ext/client_channel/channel_connectivity.c",
"src/core/ext/client_channel/client_channel.c",
"src/core/ext/client_channel/client_channel_factory.c",
"src/core/ext/client_channel/client_channel_plugin.c",
"src/core/ext/client_channel/connector.c",
"src/core/ext/client_channel/default_initial_connect_string.c",
"src/core/ext/client_channel/http_connect_handshaker.c",
"src/core/ext/client_channel/initial_connect_string.c",
"src/core/ext/client_channel/lb_policy.c",
"src/core/ext/client_channel/lb_policy_factory.c",
"src/core/ext/client_channel/lb_policy_registry.c",
"src/core/ext/client_channel/parse_address.c",
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c",
"src/core/ext/transport/chttp2/server/insecure/server_chttp2.c",
"src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c",
"src/core/ext/census/base_resources.c",
"src/core/ext/census/context.c",
"src/core/ext/census/gen/census.pb.c",
"src/core/ext/census/gen/trace_context.pb.c",
"src/core/ext/census/grpc_context.c",
"src/core/ext/census/grpc_filter.c",
"src/core/ext/census/grpc_plugin.c",
"src/core/ext/census/initialize.c",
"src/core/ext/census/mlog.c",
"src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c",
"src/core/ext/census/resource.c",
"src/core/ext/census/trace_context.c",
"src/core/ext/census/tracing.c",
], ],
hdrs = [ hdrs = [
"include/grpc++/alarm.h", "include/grpc++/alarm.h",
@ -1637,6 +1951,16 @@ cc_library(
"include/grpc/impl/codegen/sync_generic.h", "include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h", "include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_windows.h", "include/grpc/impl/codegen/sync_windows.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/grpc_posix.h",
"include/grpc/grpc_security_constants.h",
"include/grpc/slice.h",
"include/grpc/slice_buffer.h",
"include/grpc/status.h",
"include/grpc/census.h",
], ],
includes = [ includes = [
"include", "include",
@ -1646,6 +1970,7 @@ cc_library(
"//external:libssl", "//external:libssl",
":gpr", ":gpr",
":grpc_cronet", ":grpc_cronet",
"//external:nanopb",
], ],
) )
@ -2097,8 +2422,8 @@ objc_library(
"src/core/lib/transport/mdstr_hash_table.c", "src/core/lib/transport/mdstr_hash_table.c",
"src/core/lib/transport/metadata.c", "src/core/lib/transport/metadata.c",
"src/core/lib/transport/metadata_batch.c", "src/core/lib/transport/metadata_batch.c",
"src/core/lib/transport/method_config.c",
"src/core/lib/transport/pid_controller.c", "src/core/lib/transport/pid_controller.c",
"src/core/lib/transport/service_config.c",
"src/core/lib/transport/static_metadata.c", "src/core/lib/transport/static_metadata.c",
"src/core/lib/transport/timeout_encoding.c", "src/core/lib/transport/timeout_encoding.c",
"src/core/lib/transport/transport.c", "src/core/lib/transport/transport.c",
@ -2321,8 +2646,8 @@ objc_library(
"src/core/lib/transport/mdstr_hash_table.h", "src/core/lib/transport/mdstr_hash_table.h",
"src/core/lib/transport/metadata.h", "src/core/lib/transport/metadata.h",
"src/core/lib/transport/metadata_batch.h", "src/core/lib/transport/metadata_batch.h",
"src/core/lib/transport/method_config.h",
"src/core/lib/transport/pid_controller.h", "src/core/lib/transport/pid_controller.h",
"src/core/lib/transport/service_config.h",
"src/core/lib/transport/static_metadata.h", "src/core/lib/transport/static_metadata.h",
"src/core/lib/transport/timeout_encoding.h", "src/core/lib/transport/timeout_encoding.h",
"src/core/lib/transport/transport.h", "src/core/lib/transport/transport.h",

@ -391,8 +391,8 @@ add_library(grpc
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
@ -670,8 +670,8 @@ add_library(grpc_cronet
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
@ -921,8 +921,8 @@ add_library(grpc_unsecure
src/core/lib/transport/mdstr_hash_table.c src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c src/core/lib/transport/metadata_batch.c
src/core/lib/transport/method_config.c
src/core/lib/transport/pid_controller.c src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c src/core/lib/transport/transport.c
@ -1256,6 +1256,179 @@ add_library(grpc++_cronet
src/cpp/util/string_ref.cc src/cpp/util/string_ref.cc
src/cpp/util/time_cc.cc src/cpp/util/time_cc.cc
src/cpp/codegen/codegen_init.cc src/cpp/codegen/codegen_init.cc
src/core/ext/transport/chttp2/client/insecure/channel_create.c
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c
src/core/ext/transport/chttp2/transport/bin_decoder.c
src/core/ext/transport/chttp2/transport/bin_encoder.c
src/core/ext/transport/chttp2/transport/chttp2_plugin.c
src/core/ext/transport/chttp2/transport/chttp2_transport.c
src/core/ext/transport/chttp2/transport/frame_data.c
src/core/ext/transport/chttp2/transport/frame_goaway.c
src/core/ext/transport/chttp2/transport/frame_ping.c
src/core/ext/transport/chttp2/transport/frame_rst_stream.c
src/core/ext/transport/chttp2/transport/frame_settings.c
src/core/ext/transport/chttp2/transport/frame_window_update.c
src/core/ext/transport/chttp2/transport/hpack_encoder.c
src/core/ext/transport/chttp2/transport/hpack_parser.c
src/core/ext/transport/chttp2/transport/hpack_table.c
src/core/ext/transport/chttp2/transport/huffsyms.c
src/core/ext/transport/chttp2/transport/incoming_metadata.c
src/core/ext/transport/chttp2/transport/parsing.c
src/core/ext/transport/chttp2/transport/status_conversion.c
src/core/ext/transport/chttp2/transport/stream_lists.c
src/core/ext/transport/chttp2/transport/stream_map.c
src/core/ext/transport/chttp2/transport/varint.c
src/core/ext/transport/chttp2/transport/writing.c
src/core/lib/channel/channel_args.c
src/core/lib/channel/channel_stack.c
src/core/lib/channel/channel_stack_builder.c
src/core/lib/channel/compress_filter.c
src/core/lib/channel/connected_channel.c
src/core/lib/channel/deadline_filter.c
src/core/lib/channel/handshaker.c
src/core/lib/channel/http_client_filter.c
src/core/lib/channel/http_server_filter.c
src/core/lib/channel/message_size_filter.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/debug/trace.c
src/core/lib/http/format_request.c
src/core/lib/http/httpcli.c
src/core/lib/http/parser.c
src/core/lib/iomgr/closure.c
src/core/lib/iomgr/combiner.c
src/core/lib/iomgr/endpoint.c
src/core/lib/iomgr/endpoint_pair_posix.c
src/core/lib/iomgr/endpoint_pair_uv.c
src/core/lib/iomgr/endpoint_pair_windows.c
src/core/lib/iomgr/error.c
src/core/lib/iomgr/ev_epoll_linux.c
src/core/lib/iomgr/ev_poll_posix.c
src/core/lib/iomgr/ev_posix.c
src/core/lib/iomgr/exec_ctx.c
src/core/lib/iomgr/executor.c
src/core/lib/iomgr/iocp_windows.c
src/core/lib/iomgr/iomgr.c
src/core/lib/iomgr/iomgr_posix.c
src/core/lib/iomgr/iomgr_uv.c
src/core/lib/iomgr/iomgr_windows.c
src/core/lib/iomgr/load_file.c
src/core/lib/iomgr/network_status_tracker.c
src/core/lib/iomgr/polling_entity.c
src/core/lib/iomgr/pollset_set_uv.c
src/core/lib/iomgr/pollset_set_windows.c
src/core/lib/iomgr/pollset_uv.c
src/core/lib/iomgr/pollset_windows.c
src/core/lib/iomgr/resolve_address_posix.c
src/core/lib/iomgr/resolve_address_uv.c
src/core/lib/iomgr/resolve_address_windows.c
src/core/lib/iomgr/resource_quota.c
src/core/lib/iomgr/sockaddr_utils.c
src/core/lib/iomgr/socket_mutator.c
src/core/lib/iomgr/socket_utils_common_posix.c
src/core/lib/iomgr/socket_utils_linux.c
src/core/lib/iomgr/socket_utils_posix.c
src/core/lib/iomgr/socket_utils_uv.c
src/core/lib/iomgr/socket_utils_windows.c
src/core/lib/iomgr/socket_windows.c
src/core/lib/iomgr/tcp_client_posix.c
src/core/lib/iomgr/tcp_client_uv.c
src/core/lib/iomgr/tcp_client_windows.c
src/core/lib/iomgr/tcp_posix.c
src/core/lib/iomgr/tcp_server_posix.c
src/core/lib/iomgr/tcp_server_uv.c
src/core/lib/iomgr/tcp_server_windows.c
src/core/lib/iomgr/tcp_uv.c
src/core/lib/iomgr/tcp_windows.c
src/core/lib/iomgr/time_averaged_stats.c
src/core/lib/iomgr/timer_generic.c
src/core/lib/iomgr/timer_heap.c
src/core/lib/iomgr/timer_uv.c
src/core/lib/iomgr/udp_server.c
src/core/lib/iomgr/unix_sockets_posix.c
src/core/lib/iomgr/unix_sockets_posix_noop.c
src/core/lib/iomgr/wakeup_fd_cv.c
src/core/lib/iomgr/wakeup_fd_eventfd.c
src/core/lib/iomgr/wakeup_fd_nospecial.c
src/core/lib/iomgr/wakeup_fd_pipe.c
src/core/lib/iomgr/wakeup_fd_posix.c
src/core/lib/iomgr/workqueue_uv.c
src/core/lib/iomgr/workqueue_windows.c
src/core/lib/json/json.c
src/core/lib/json/json_reader.c
src/core/lib/json/json_string.c
src/core/lib/json/json_writer.c
src/core/lib/slice/percent_encoding.c
src/core/lib/slice/slice.c
src/core/lib/slice/slice_buffer.c
src/core/lib/slice/slice_string_helpers.c
src/core/lib/surface/alarm.c
src/core/lib/surface/api_trace.c
src/core/lib/surface/byte_buffer.c
src/core/lib/surface/byte_buffer_reader.c
src/core/lib/surface/call.c
src/core/lib/surface/call_details.c
src/core/lib/surface/call_log_batch.c
src/core/lib/surface/channel.c
src/core/lib/surface/channel_init.c
src/core/lib/surface/channel_ping.c
src/core/lib/surface/channel_stack_type.c
src/core/lib/surface/completion_queue.c
src/core/lib/surface/event_string.c
src/core/lib/surface/lame_client.c
src/core/lib/surface/metadata_array.c
src/core/lib/surface/server.c
src/core/lib/surface/validate_metadata.c
src/core/lib/surface/version.c
src/core/lib/transport/byte_stream.c
src/core/lib/transport/connectivity_state.c
src/core/lib/transport/mdstr_hash_table.c
src/core/lib/transport/metadata.c
src/core/lib/transport/metadata_batch.c
src/core/lib/transport/pid_controller.c
src/core/lib/transport/service_config.c
src/core/lib/transport/static_metadata.c
src/core/lib/transport/timeout_encoding.c
src/core/lib/transport/transport.c
src/core/lib/transport/transport_op_string.c
src/core/ext/transport/chttp2/alpn/alpn.c
src/core/ext/client_channel/channel_connectivity.c
src/core/ext/client_channel/client_channel.c
src/core/ext/client_channel/client_channel_factory.c
src/core/ext/client_channel/client_channel_plugin.c
src/core/ext/client_channel/connector.c
src/core/ext/client_channel/default_initial_connect_string.c
src/core/ext/client_channel/http_connect_handshaker.c
src/core/ext/client_channel/initial_connect_string.c
src/core/ext/client_channel/lb_policy.c
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
src/core/ext/client_channel/parse_address.c
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c
src/core/ext/transport/chttp2/server/insecure/server_chttp2.c
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c
src/core/ext/census/base_resources.c
src/core/ext/census/context.c
src/core/ext/census/gen/census.pb.c
src/core/ext/census/gen/trace_context.pb.c
src/core/ext/census/grpc_context.c
src/core/ext/census/grpc_filter.c
src/core/ext/census/grpc_plugin.c
src/core/ext/census/initialize.c
src/core/ext/census/mlog.c
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
src/core/ext/census/resource.c
src/core/ext/census/trace_context.c
src/core/ext/census/tracing.c
third_party/nanopb/pb_common.c
third_party/nanopb/pb_decode.c
third_party/nanopb/pb_encode.c
) )
target_include_directories(grpc++_cronet target_include_directories(grpc++_cronet
@ -1362,6 +1535,16 @@ foreach(_hdr
include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_generic.h
include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_posix.h
include/grpc/impl/codegen/sync_windows.h include/grpc/impl/codegen/sync_windows.h
include/grpc/byte_buffer.h
include/grpc/byte_buffer_reader.h
include/grpc/compression.h
include/grpc/grpc.h
include/grpc/grpc_posix.h
include/grpc/grpc_security_constants.h
include/grpc/slice.h
include/grpc/slice_buffer.h
include/grpc/status.h
include/grpc/census.h
) )
string(REPLACE "include/" "" _path ${_hdr}) string(REPLACE "include/" "" _path ${_hdr})
get_filename_component(_path ${_path} PATH) get_filename_component(_path ${_path} PATH)

@ -1057,6 +1057,7 @@ wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test
alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack
channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
@ -1445,6 +1446,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_fullstack \
$(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \
$(BINDIR)/$(CONFIG)/cli_call_test \ $(BINDIR)/$(CONFIG)/cli_call_test \
@ -1537,6 +1539,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_fullstack \
$(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \
$(BINDIR)/$(CONFIG)/cli_call_test \ $(BINDIR)/$(CONFIG)/cli_call_test \
@ -1842,6 +1845,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing auth_property_iterator_test" $(E) "[RUN] Testing auth_property_iterator_test"
$(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
$(E) "[RUN] Testing bm_fullstack"
$(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 )
$(E) "[RUN] Testing channel_arguments_test" $(E) "[RUN] Testing channel_arguments_test"
$(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 )
$(E) "[RUN] Testing channel_filter_test" $(E) "[RUN] Testing channel_filter_test"
@ -2725,8 +2730,8 @@ LIBGRPC_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3022,8 +3027,8 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3310,8 +3315,8 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3527,8 +3532,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \
@ -3974,6 +3979,179 @@ LIBGRPC++_CRONET_SRC = \
src/cpp/util/string_ref.cc \ src/cpp/util/string_ref.cc \
src/cpp/util/time_cc.cc \ src/cpp/util/time_cc.cc \
src/cpp/codegen/codegen_init.cc \ src/cpp/codegen/codegen_init.cc \
src/core/ext/transport/chttp2/client/insecure/channel_create.c \
src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \
src/core/ext/transport/chttp2/transport/bin_decoder.c \
src/core/ext/transport/chttp2/transport/bin_encoder.c \
src/core/ext/transport/chttp2/transport/chttp2_plugin.c \
src/core/ext/transport/chttp2/transport/chttp2_transport.c \
src/core/ext/transport/chttp2/transport/frame_data.c \
src/core/ext/transport/chttp2/transport/frame_goaway.c \
src/core/ext/transport/chttp2/transport/frame_ping.c \
src/core/ext/transport/chttp2/transport/frame_rst_stream.c \
src/core/ext/transport/chttp2/transport/frame_settings.c \
src/core/ext/transport/chttp2/transport/frame_window_update.c \
src/core/ext/transport/chttp2/transport/hpack_encoder.c \
src/core/ext/transport/chttp2/transport/hpack_parser.c \
src/core/ext/transport/chttp2/transport/hpack_table.c \
src/core/ext/transport/chttp2/transport/huffsyms.c \
src/core/ext/transport/chttp2/transport/incoming_metadata.c \
src/core/ext/transport/chttp2/transport/parsing.c \
src/core/ext/transport/chttp2/transport/status_conversion.c \
src/core/ext/transport/chttp2/transport/stream_lists.c \
src/core/ext/transport/chttp2/transport/stream_map.c \
src/core/ext/transport/chttp2/transport/varint.c \
src/core/ext/transport/chttp2/transport/writing.c \
src/core/lib/channel/channel_args.c \
src/core/lib/channel/channel_stack.c \
src/core/lib/channel/channel_stack_builder.c \
src/core/lib/channel/compress_filter.c \
src/core/lib/channel/connected_channel.c \
src/core/lib/channel/deadline_filter.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
src/core/lib/http/format_request.c \
src/core/lib/http/httpcli.c \
src/core/lib/http/parser.c \
src/core/lib/iomgr/closure.c \
src/core/lib/iomgr/combiner.c \
src/core/lib/iomgr/endpoint.c \
src/core/lib/iomgr/endpoint_pair_posix.c \
src/core/lib/iomgr/endpoint_pair_uv.c \
src/core/lib/iomgr/endpoint_pair_windows.c \
src/core/lib/iomgr/error.c \
src/core/lib/iomgr/ev_epoll_linux.c \
src/core/lib/iomgr/ev_poll_posix.c \
src/core/lib/iomgr/ev_posix.c \
src/core/lib/iomgr/exec_ctx.c \
src/core/lib/iomgr/executor.c \
src/core/lib/iomgr/iocp_windows.c \
src/core/lib/iomgr/iomgr.c \
src/core/lib/iomgr/iomgr_posix.c \
src/core/lib/iomgr/iomgr_uv.c \
src/core/lib/iomgr/iomgr_windows.c \
src/core/lib/iomgr/load_file.c \
src/core/lib/iomgr/network_status_tracker.c \
src/core/lib/iomgr/polling_entity.c \
src/core/lib/iomgr/pollset_set_uv.c \
src/core/lib/iomgr/pollset_set_windows.c \
src/core/lib/iomgr/pollset_uv.c \
src/core/lib/iomgr/pollset_windows.c \
src/core/lib/iomgr/resolve_address_posix.c \
src/core/lib/iomgr/resolve_address_uv.c \
src/core/lib/iomgr/resolve_address_windows.c \
src/core/lib/iomgr/resource_quota.c \
src/core/lib/iomgr/sockaddr_utils.c \
src/core/lib/iomgr/socket_mutator.c \
src/core/lib/iomgr/socket_utils_common_posix.c \
src/core/lib/iomgr/socket_utils_linux.c \
src/core/lib/iomgr/socket_utils_posix.c \
src/core/lib/iomgr/socket_utils_uv.c \
src/core/lib/iomgr/socket_utils_windows.c \
src/core/lib/iomgr/socket_windows.c \
src/core/lib/iomgr/tcp_client_posix.c \
src/core/lib/iomgr/tcp_client_uv.c \
src/core/lib/iomgr/tcp_client_windows.c \
src/core/lib/iomgr/tcp_posix.c \
src/core/lib/iomgr/tcp_server_posix.c \
src/core/lib/iomgr/tcp_server_uv.c \
src/core/lib/iomgr/tcp_server_windows.c \
src/core/lib/iomgr/tcp_uv.c \
src/core/lib/iomgr/tcp_windows.c \
src/core/lib/iomgr/time_averaged_stats.c \
src/core/lib/iomgr/timer_generic.c \
src/core/lib/iomgr/timer_heap.c \
src/core/lib/iomgr/timer_uv.c \
src/core/lib/iomgr/udp_server.c \
src/core/lib/iomgr/unix_sockets_posix.c \
src/core/lib/iomgr/unix_sockets_posix_noop.c \
src/core/lib/iomgr/wakeup_fd_cv.c \
src/core/lib/iomgr/wakeup_fd_eventfd.c \
src/core/lib/iomgr/wakeup_fd_nospecial.c \
src/core/lib/iomgr/wakeup_fd_pipe.c \
src/core/lib/iomgr/wakeup_fd_posix.c \
src/core/lib/iomgr/workqueue_uv.c \
src/core/lib/iomgr/workqueue_windows.c \
src/core/lib/json/json.c \
src/core/lib/json/json_reader.c \
src/core/lib/json/json_string.c \
src/core/lib/json/json_writer.c \
src/core/lib/slice/percent_encoding.c \
src/core/lib/slice/slice.c \
src/core/lib/slice/slice_buffer.c \
src/core/lib/slice/slice_string_helpers.c \
src/core/lib/surface/alarm.c \
src/core/lib/surface/api_trace.c \
src/core/lib/surface/byte_buffer.c \
src/core/lib/surface/byte_buffer_reader.c \
src/core/lib/surface/call.c \
src/core/lib/surface/call_details.c \
src/core/lib/surface/call_log_batch.c \
src/core/lib/surface/channel.c \
src/core/lib/surface/channel_init.c \
src/core/lib/surface/channel_ping.c \
src/core/lib/surface/channel_stack_type.c \
src/core/lib/surface/completion_queue.c \
src/core/lib/surface/event_string.c \
src/core/lib/surface/lame_client.c \
src/core/lib/surface/metadata_array.c \
src/core/lib/surface/server.c \
src/core/lib/surface/validate_metadata.c \
src/core/lib/surface/version.c \
src/core/lib/transport/byte_stream.c \
src/core/lib/transport/connectivity_state.c \
src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \
src/core/lib/transport/transport_op_string.c \
src/core/ext/transport/chttp2/alpn/alpn.c \
src/core/ext/client_channel/channel_connectivity.c \
src/core/ext/client_channel/client_channel.c \
src/core/ext/client_channel/client_channel_factory.c \
src/core/ext/client_channel/client_channel_plugin.c \
src/core/ext/client_channel/connector.c \
src/core/ext/client_channel/default_initial_connect_string.c \
src/core/ext/client_channel/http_connect_handshaker.c \
src/core/ext/client_channel/initial_connect_string.c \
src/core/ext/client_channel/lb_policy.c \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/parse_address.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \
src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \
src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \
src/core/ext/census/base_resources.c \
src/core/ext/census/context.c \
src/core/ext/census/gen/census.pb.c \
src/core/ext/census/gen/trace_context.pb.c \
src/core/ext/census/grpc_context.c \
src/core/ext/census/grpc_filter.c \
src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
src/core/ext/census/resource.c \
src/core/ext/census/trace_context.c \
src/core/ext/census/tracing.c \
third_party/nanopb/pb_common.c \
third_party/nanopb/pb_decode.c \
third_party/nanopb/pb_encode.c \
PUBLIC_HEADERS_CXX += \ PUBLIC_HEADERS_CXX += \
include/grpc++/alarm.h \ include/grpc++/alarm.h \
@ -4063,6 +4241,16 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_generic.h \
include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_posix.h \
include/grpc/impl/codegen/sync_windows.h \ include/grpc/impl/codegen/sync_windows.h \
include/grpc/byte_buffer.h \
include/grpc/byte_buffer_reader.h \
include/grpc/compression.h \
include/grpc/grpc.h \
include/grpc/grpc_posix.h \
include/grpc/grpc_security_constants.h \
include/grpc/slice.h \
include/grpc/slice_buffer.h \
include/grpc/status.h \
include/grpc/census.h \
LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC)))) LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC))))
@ -11518,6 +11706,49 @@ endif
endif endif
BM_FULLSTACK_SRC = \
test/cpp/microbenchmarks/bm_fullstack.cc \
BM_FULLSTACK_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_FULLSTACK_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_fullstack: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/bm_fullstack: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_fullstack: $(PROTOBUF_DEP) $(BM_FULLSTACK_OBJS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_OBJS) $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack.o: $(LIBDIR)/$(CONFIG)/libgoogle_benchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_bm_fullstack: $(BM_FULLSTACK_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_FULLSTACK_OBJS:.o=.dep)
endif
endif
CHANNEL_ARGUMENTS_TEST_SRC = \ CHANNEL_ARGUMENTS_TEST_SRC = \
test/cpp/common/channel_arguments_test.cc \ test/cpp/common/channel_arguments_test.cc \

@ -671,8 +671,8 @@
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',

@ -254,8 +254,8 @@ filegroups:
- src/core/lib/transport/mdstr_hash_table.h - src/core/lib/transport/mdstr_hash_table.h
- src/core/lib/transport/metadata.h - src/core/lib/transport/metadata.h
- src/core/lib/transport/metadata_batch.h - src/core/lib/transport/metadata_batch.h
- src/core/lib/transport/method_config.h
- src/core/lib/transport/pid_controller.h - src/core/lib/transport/pid_controller.h
- src/core/lib/transport/service_config.h
- src/core/lib/transport/static_metadata.h - src/core/lib/transport/static_metadata.h
- src/core/lib/transport/timeout_encoding.h - src/core/lib/transport/timeout_encoding.h
- src/core/lib/transport/transport.h - src/core/lib/transport/transport.h
@ -367,8 +367,8 @@ filegroups:
- src/core/lib/transport/mdstr_hash_table.c - src/core/lib/transport/mdstr_hash_table.c
- src/core/lib/transport/metadata.c - src/core/lib/transport/metadata.c
- src/core/lib/transport/metadata_batch.c - src/core/lib/transport/metadata_batch.c
- src/core/lib/transport/method_config.c
- src/core/lib/transport/pid_controller.c - src/core/lib/transport/pid_controller.c
- src/core/lib/transport/service_config.c
- src/core/lib/transport/static_metadata.c - src/core/lib/transport/static_metadata.c
- src/core/lib/transport/timeout_encoding.c - src/core/lib/transport/timeout_encoding.c
- src/core/lib/transport/transport.c - src/core/lib/transport/transport.c
@ -1039,6 +1039,9 @@ libs:
- grpc++_base - grpc++_base
- grpc++_codegen_base - grpc++_codegen_base
- grpc++_codegen_base_src - grpc++_codegen_base_src
- grpc_transport_chttp2_client_insecure
- grpc_transport_chttp2_server_insecure
- census
platforms: platforms:
- linux - linux
secure: true secure: true
@ -2821,6 +2824,19 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: bm_fullstack
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_fullstack.cc
deps:
- google_benchmark
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
- name: channel_arguments_test - name: channel_arguments_test
gtest: true gtest: true
build: test build: test

@ -187,8 +187,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/transport/mdstr_hash_table.c \ src/core/lib/transport/mdstr_hash_table.c \
src/core/lib/transport/metadata.c \ src/core/lib/transport/metadata.c \
src/core/lib/transport/metadata_batch.c \ src/core/lib/transport/metadata_batch.c \
src/core/lib/transport/method_config.c \
src/core/lib/transport/pid_controller.c \ src/core/lib/transport/pid_controller.c \
src/core/lib/transport/service_config.c \
src/core/lib/transport/static_metadata.c \ src/core/lib/transport/static_metadata.c \
src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/timeout_encoding.c \
src/core/lib/transport/transport.c \ src/core/lib/transport/transport.c \

@ -6,7 +6,7 @@
}, },
"dependencies": { "dependencies": {
"Google.Protobuf": "3.0.0", "Google.Protobuf": "3.0.0",
"Grpc": "1.0.0", "Grpc": "1.0.1",
}, },
"frameworks": { "frameworks": {
"net45": { "net45": {
@ -17,6 +17,15 @@
"dependencies": { "dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1" "Microsoft.NETCore.Platforms": "1.0.1"
} }
},
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": "dnxcore50"
} }
} }
} }

@ -7,7 +7,7 @@
}, },
"dependencies": { "dependencies": {
"Google.Protobuf": "3.0.0", "Google.Protobuf": "3.0.0",
"Grpc": "1.0.0", "Grpc": "1.0.1",
"Greeter": { "Greeter": {
"target": "project" "target": "project"
} }
@ -21,6 +21,15 @@
"dependencies": { "dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1" "Microsoft.NETCore.Platforms": "1.0.1"
} }
},
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": "dnxcore50"
} }
} }
} }

@ -7,7 +7,7 @@
}, },
"dependencies": { "dependencies": {
"Google.Protobuf": "3.0.0", "Google.Protobuf": "3.0.0",
"Grpc": "1.0.0", "Grpc": "1.0.1",
"Greeter": { "Greeter": {
"target": "project" "target": "project"
} }
@ -21,6 +21,15 @@
"dependencies": { "dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1" "Microsoft.NETCore.Platforms": "1.0.1"
} }
},
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
}
},
"imports": "dnxcore50"
} }
} }
} }

@ -35,9 +35,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL"> <Reference Include="Grpc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.1.0.0\lib\net45\Grpc.Core.dll</HintPath> <HintPath>..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -61,11 +61,11 @@
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" /> <Import Project="..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets'))" /> <Error Condition="!Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets'))" />
</Target> </Target>
</Project> </Project>

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="Grpc" version="1.0.0" targetFramework="net45" /> <package id="Grpc" version="1.0.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Core" version="1.0.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Grpc.Tools" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Tools" version="1.0.1" targetFramework="net45" />
</packages> </packages>

@ -35,9 +35,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL"> <Reference Include="Grpc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.1.0.0\lib\net45\Grpc.Core.dll</HintPath> <HintPath>..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -59,11 +59,11 @@
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<Import Project="..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" /> <Import Project="..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets'))" /> <Error Condition="!Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets'))" />
</Target> </Target>
</Project> </Project>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="Grpc" version="1.0.0" targetFramework="net45" /> <package id="Grpc" version="1.0.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Core" version="1.0.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
</packages> </packages>

@ -35,9 +35,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL"> <Reference Include="Grpc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.1.0.0\lib\net45\Grpc.Core.dll</HintPath> <HintPath>..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@ -59,11 +59,11 @@
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<Import Project="..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" /> <Import Project="..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets'))" /> <Error Condition="!Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets'))" />
</Target> </Target>
</Project> </Project>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="Grpc" version="1.0.0" targetFramework="net45" /> <package id="Grpc" version="1.0.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Core" version="1.0.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
</packages> </packages>

@ -10,7 +10,6 @@ using scg = global::System.Collections.Generic;
namespace Routeguide { namespace Routeguide {
/// <summary>Holder for reflection information generated from route_guide.proto</summary> /// <summary>Holder for reflection information generated from route_guide.proto</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class RouteGuideReflection { public static partial class RouteGuideReflection {
#region Descriptor #region Descriptor
@ -59,30 +58,35 @@ namespace Routeguide {
/// Latitudes should be in the range +/- 90 degrees and longitude should be in /// Latitudes should be in the range +/- 90 degrees and longitude should be in
/// the range +/- 180 degrees (inclusive). /// the range +/- 180 degrees (inclusive).
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class Point : pb::IMessage<Point> { public sealed partial class Point : pb::IMessage<Point> {
private static readonly pb::MessageParser<Point> _parser = new pb::MessageParser<Point>(() => new Point()); private static readonly pb::MessageParser<Point> _parser = new pb::MessageParser<Point>(() => new Point());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Point> Parser { get { return _parser; } } public static pb::MessageParser<Point> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[0]; } get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[0]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor { pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; } get { return Descriptor; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Point() { public Point() {
OnConstruction(); OnConstruction();
} }
partial void OnConstruction(); partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Point(Point other) : this() { public Point(Point other) : this() {
latitude_ = other.latitude_; latitude_ = other.latitude_;
longitude_ = other.longitude_; longitude_ = other.longitude_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Point Clone() { public Point Clone() {
return new Point(this); return new Point(this);
} }
@ -90,6 +94,7 @@ namespace Routeguide {
/// <summary>Field number for the "latitude" field.</summary> /// <summary>Field number for the "latitude" field.</summary>
public const int LatitudeFieldNumber = 1; public const int LatitudeFieldNumber = 1;
private int latitude_; private int latitude_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Latitude { public int Latitude {
get { return latitude_; } get { return latitude_; }
set { set {
@ -100,6 +105,7 @@ namespace Routeguide {
/// <summary>Field number for the "longitude" field.</summary> /// <summary>Field number for the "longitude" field.</summary>
public const int LongitudeFieldNumber = 2; public const int LongitudeFieldNumber = 2;
private int longitude_; private int longitude_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Longitude { public int Longitude {
get { return longitude_; } get { return longitude_; }
set { set {
@ -107,10 +113,12 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as Point); return Equals(other as Point);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Point other) { public bool Equals(Point other) {
if (ReferenceEquals(other, null)) { if (ReferenceEquals(other, null)) {
return false; return false;
@ -123,6 +131,7 @@ namespace Routeguide {
return true; return true;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (Latitude != 0) hash ^= Latitude.GetHashCode(); if (Latitude != 0) hash ^= Latitude.GetHashCode();
@ -130,10 +139,12 @@ namespace Routeguide {
return hash; return hash;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() { public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this); return pb::JsonFormatter.ToDiagnosticString(this);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (Latitude != 0) { if (Latitude != 0) {
output.WriteRawTag(8); output.WriteRawTag(8);
@ -145,6 +156,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (Latitude != 0) { if (Latitude != 0) {
@ -156,6 +168,7 @@ namespace Routeguide {
return size; return size;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Point other) { public void MergeFrom(Point other) {
if (other == null) { if (other == null) {
return; return;
@ -168,6 +181,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) { public void MergeFrom(pb::CodedInputStream input) {
uint tag; uint tag;
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
@ -193,30 +207,35 @@ namespace Routeguide {
/// A latitude-longitude rectangle, represented as two diagonally opposite /// A latitude-longitude rectangle, represented as two diagonally opposite
/// points "lo" and "hi". /// points "lo" and "hi".
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class Rectangle : pb::IMessage<Rectangle> { public sealed partial class Rectangle : pb::IMessage<Rectangle> {
private static readonly pb::MessageParser<Rectangle> _parser = new pb::MessageParser<Rectangle>(() => new Rectangle()); private static readonly pb::MessageParser<Rectangle> _parser = new pb::MessageParser<Rectangle>(() => new Rectangle());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Rectangle> Parser { get { return _parser; } } public static pb::MessageParser<Rectangle> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[1]; } get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[1]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor { pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; } get { return Descriptor; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle() { public Rectangle() {
OnConstruction(); OnConstruction();
} }
partial void OnConstruction(); partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle(Rectangle other) : this() { public Rectangle(Rectangle other) : this() {
Lo = other.lo_ != null ? other.Lo.Clone() : null; Lo = other.lo_ != null ? other.Lo.Clone() : null;
Hi = other.hi_ != null ? other.Hi.Clone() : null; Hi = other.hi_ != null ? other.Hi.Clone() : null;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Rectangle Clone() { public Rectangle Clone() {
return new Rectangle(this); return new Rectangle(this);
} }
@ -227,6 +246,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// One corner of the rectangle. /// One corner of the rectangle.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Lo { public global::Routeguide.Point Lo {
get { return lo_; } get { return lo_; }
set { set {
@ -240,6 +260,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The other corner of the rectangle. /// The other corner of the rectangle.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Hi { public global::Routeguide.Point Hi {
get { return hi_; } get { return hi_; }
set { set {
@ -247,10 +268,12 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as Rectangle); return Equals(other as Rectangle);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Rectangle other) { public bool Equals(Rectangle other) {
if (ReferenceEquals(other, null)) { if (ReferenceEquals(other, null)) {
return false; return false;
@ -263,6 +286,7 @@ namespace Routeguide {
return true; return true;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (lo_ != null) hash ^= Lo.GetHashCode(); if (lo_ != null) hash ^= Lo.GetHashCode();
@ -270,10 +294,12 @@ namespace Routeguide {
return hash; return hash;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() { public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this); return pb::JsonFormatter.ToDiagnosticString(this);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (lo_ != null) { if (lo_ != null) {
output.WriteRawTag(10); output.WriteRawTag(10);
@ -285,6 +311,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (lo_ != null) { if (lo_ != null) {
@ -296,6 +323,7 @@ namespace Routeguide {
return size; return size;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Rectangle other) { public void MergeFrom(Rectangle other) {
if (other == null) { if (other == null) {
return; return;
@ -314,6 +342,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) { public void MergeFrom(pb::CodedInputStream input) {
uint tag; uint tag;
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
@ -346,30 +375,35 @@ namespace Routeguide {
/// ///
/// If a feature could not be named, the name is empty. /// If a feature could not be named, the name is empty.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class Feature : pb::IMessage<Feature> { public sealed partial class Feature : pb::IMessage<Feature> {
private static readonly pb::MessageParser<Feature> _parser = new pb::MessageParser<Feature>(() => new Feature()); private static readonly pb::MessageParser<Feature> _parser = new pb::MessageParser<Feature>(() => new Feature());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<Feature> Parser { get { return _parser; } } public static pb::MessageParser<Feature> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[2]; } get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[2]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor { pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; } get { return Descriptor; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature() { public Feature() {
OnConstruction(); OnConstruction();
} }
partial void OnConstruction(); partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature(Feature other) : this() { public Feature(Feature other) : this() {
name_ = other.name_; name_ = other.name_;
Location = other.location_ != null ? other.Location.Clone() : null; Location = other.location_ != null ? other.Location.Clone() : null;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public Feature Clone() { public Feature Clone() {
return new Feature(this); return new Feature(this);
} }
@ -380,6 +414,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The name of the feature. /// The name of the feature.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Name { public string Name {
get { return name_; } get { return name_; }
set { set {
@ -393,6 +428,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The point where the feature is detected. /// The point where the feature is detected.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Location { public global::Routeguide.Point Location {
get { return location_; } get { return location_; }
set { set {
@ -400,10 +436,12 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as Feature); return Equals(other as Feature);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(Feature other) { public bool Equals(Feature other) {
if (ReferenceEquals(other, null)) { if (ReferenceEquals(other, null)) {
return false; return false;
@ -416,6 +454,7 @@ namespace Routeguide {
return true; return true;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode(); if (Name.Length != 0) hash ^= Name.GetHashCode();
@ -423,10 +462,12 @@ namespace Routeguide {
return hash; return hash;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() { public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this); return pb::JsonFormatter.ToDiagnosticString(this);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) { if (Name.Length != 0) {
output.WriteRawTag(10); output.WriteRawTag(10);
@ -438,6 +479,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (Name.Length != 0) { if (Name.Length != 0) {
@ -449,6 +491,7 @@ namespace Routeguide {
return size; return size;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(Feature other) { public void MergeFrom(Feature other) {
if (other == null) { if (other == null) {
return; return;
@ -464,6 +507,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) { public void MergeFrom(pb::CodedInputStream input) {
uint tag; uint tag;
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
@ -491,30 +535,35 @@ namespace Routeguide {
/// <summary> /// <summary>
/// A RouteNote is a message sent while at a given point. /// A RouteNote is a message sent while at a given point.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class RouteNote : pb::IMessage<RouteNote> { public sealed partial class RouteNote : pb::IMessage<RouteNote> {
private static readonly pb::MessageParser<RouteNote> _parser = new pb::MessageParser<RouteNote>(() => new RouteNote()); private static readonly pb::MessageParser<RouteNote> _parser = new pb::MessageParser<RouteNote>(() => new RouteNote());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RouteNote> Parser { get { return _parser; } } public static pb::MessageParser<RouteNote> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[3]; } get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[3]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor { pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; } get { return Descriptor; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote() { public RouteNote() {
OnConstruction(); OnConstruction();
} }
partial void OnConstruction(); partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote(RouteNote other) : this() { public RouteNote(RouteNote other) : this() {
Location = other.location_ != null ? other.Location.Clone() : null; Location = other.location_ != null ? other.Location.Clone() : null;
message_ = other.message_; message_ = other.message_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteNote Clone() { public RouteNote Clone() {
return new RouteNote(this); return new RouteNote(this);
} }
@ -525,6 +574,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The location from which the message is sent. /// The location from which the message is sent.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Routeguide.Point Location { public global::Routeguide.Point Location {
get { return location_; } get { return location_; }
set { set {
@ -538,6 +588,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The message to be sent. /// The message to be sent.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string Message { public string Message {
get { return message_; } get { return message_; }
set { set {
@ -545,10 +596,12 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as RouteNote); return Equals(other as RouteNote);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(RouteNote other) { public bool Equals(RouteNote other) {
if (ReferenceEquals(other, null)) { if (ReferenceEquals(other, null)) {
return false; return false;
@ -561,6 +614,7 @@ namespace Routeguide {
return true; return true;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (location_ != null) hash ^= Location.GetHashCode(); if (location_ != null) hash ^= Location.GetHashCode();
@ -568,10 +622,12 @@ namespace Routeguide {
return hash; return hash;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() { public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this); return pb::JsonFormatter.ToDiagnosticString(this);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (location_ != null) { if (location_ != null) {
output.WriteRawTag(10); output.WriteRawTag(10);
@ -583,6 +639,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (location_ != null) { if (location_ != null) {
@ -594,6 +651,7 @@ namespace Routeguide {
return size; return size;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(RouteNote other) { public void MergeFrom(RouteNote other) {
if (other == null) { if (other == null) {
return; return;
@ -609,6 +667,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) { public void MergeFrom(pb::CodedInputStream input) {
uint tag; uint tag;
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {
@ -640,25 +699,29 @@ namespace Routeguide {
/// detected features, and the total distance covered as the cumulative sum of /// detected features, and the total distance covered as the cumulative sum of
/// the distance between each point. /// the distance between each point.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class RouteSummary : pb::IMessage<RouteSummary> { public sealed partial class RouteSummary : pb::IMessage<RouteSummary> {
private static readonly pb::MessageParser<RouteSummary> _parser = new pb::MessageParser<RouteSummary>(() => new RouteSummary()); private static readonly pb::MessageParser<RouteSummary> _parser = new pb::MessageParser<RouteSummary>(() => new RouteSummary());
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pb::MessageParser<RouteSummary> Parser { get { return _parser; } } public static pb::MessageParser<RouteSummary> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[4]; } get { return global::Routeguide.RouteGuideReflection.Descriptor.MessageTypes[4]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
pbr::MessageDescriptor pb::IMessage.Descriptor { pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; } get { return Descriptor; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteSummary() { public RouteSummary() {
OnConstruction(); OnConstruction();
} }
partial void OnConstruction(); partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteSummary(RouteSummary other) : this() { public RouteSummary(RouteSummary other) : this() {
pointCount_ = other.pointCount_; pointCount_ = other.pointCount_;
featureCount_ = other.featureCount_; featureCount_ = other.featureCount_;
@ -666,6 +729,7 @@ namespace Routeguide {
elapsedTime_ = other.elapsedTime_; elapsedTime_ = other.elapsedTime_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public RouteSummary Clone() { public RouteSummary Clone() {
return new RouteSummary(this); return new RouteSummary(this);
} }
@ -676,6 +740,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The number of points received. /// The number of points received.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int PointCount { public int PointCount {
get { return pointCount_; } get { return pointCount_; }
set { set {
@ -689,6 +754,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The number of known features passed while traversing the route. /// The number of known features passed while traversing the route.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int FeatureCount { public int FeatureCount {
get { return featureCount_; } get { return featureCount_; }
set { set {
@ -702,6 +768,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The distance covered in metres. /// The distance covered in metres.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int Distance { public int Distance {
get { return distance_; } get { return distance_; }
set { set {
@ -715,6 +782,7 @@ namespace Routeguide {
/// <summary> /// <summary>
/// The duration of the traversal in seconds. /// The duration of the traversal in seconds.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ElapsedTime { public int ElapsedTime {
get { return elapsedTime_; } get { return elapsedTime_; }
set { set {
@ -722,10 +790,12 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as RouteSummary); return Equals(other as RouteSummary);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool Equals(RouteSummary other) { public bool Equals(RouteSummary other) {
if (ReferenceEquals(other, null)) { if (ReferenceEquals(other, null)) {
return false; return false;
@ -740,6 +810,7 @@ namespace Routeguide {
return true; return true;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
if (PointCount != 0) hash ^= PointCount.GetHashCode(); if (PointCount != 0) hash ^= PointCount.GetHashCode();
@ -749,10 +820,12 @@ namespace Routeguide {
return hash; return hash;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override string ToString() { public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this); return pb::JsonFormatter.ToDiagnosticString(this);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) { public void WriteTo(pb::CodedOutputStream output) {
if (PointCount != 0) { if (PointCount != 0) {
output.WriteRawTag(8); output.WriteRawTag(8);
@ -772,6 +845,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
if (PointCount != 0) { if (PointCount != 0) {
@ -789,6 +863,7 @@ namespace Routeguide {
return size; return size;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(RouteSummary other) { public void MergeFrom(RouteSummary other) {
if (other == null) { if (other == null) {
return; return;
@ -807,6 +882,7 @@ namespace Routeguide {
} }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void MergeFrom(pb::CodedInputStream input) { public void MergeFrom(pb::CodedInputStream input) {
uint tag; uint tag;
while ((tag = input.ReadTag()) != 0) { while ((tag = input.ReadTag()) != 0) {

@ -35,9 +35,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL"> <Reference Include="Grpc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.1.0.0\lib\net45\Grpc.Core.dll</HintPath> <HintPath>..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
@ -74,12 +74,12 @@
</None> </None>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" /> <Import Project="..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets'))" /> <Error Condition="!Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets'))" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="Grpc" version="1.0.0" targetFramework="net45" /> <package id="Grpc" version="1.0.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Core" version="1.0.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> </packages>

@ -37,9 +37,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL"> <Reference Include="Grpc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.1.0.0\lib\net45\Grpc.Core.dll</HintPath> <HintPath>..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
@ -71,12 +71,12 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" /> <Import Project="..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets'))" /> <Error Condition="!Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets'))" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="Grpc" version="1.0.0" targetFramework="net45" /> <package id="Grpc" version="1.0.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Core" version="1.0.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> </packages>

@ -37,9 +37,9 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="Grpc.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL"> <Reference Include="Grpc.Core, Version=1.0.1.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Grpc.Core.1.0.0\lib\net45\Grpc.Core.dll</HintPath> <HintPath>..\packages\Grpc.Core.1.0.1\lib\net45\Grpc.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
@ -72,12 +72,12 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" /> <Import Project="..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup> <PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.0\build\net45\Grpc.Core.targets'))" /> <Error Condition="!Exists('..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.1.0.1\build\net45\Grpc.Core.targets'))" />
</Target> </Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="Grpc" version="1.0.0" targetFramework="net45" /> <package id="Grpc" version="1.0.1" targetFramework="net45" />
<package id="Grpc.Core" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Core" version="1.0.1" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="Grpc.Tools" version="1.0.0" targetFramework="net45" /> <package id="Grpc.Tools" version="1.0.1" targetFramework="net45" />
</packages> </packages>

@ -336,8 +336,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.h', 'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport.h',
@ -529,8 +529,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.c', 'src/core/lib/transport/mdstr_hash_table.c',
'src/core/lib/transport/metadata.c', 'src/core/lib/transport/metadata.c',
'src/core/lib/transport/metadata_batch.c', 'src/core/lib/transport/metadata_batch.c',
'src/core/lib/transport/method_config.c',
'src/core/lib/transport/pid_controller.c', 'src/core/lib/transport/pid_controller.c',
'src/core/lib/transport/service_config.c',
'src/core/lib/transport/static_metadata.c', 'src/core/lib/transport/static_metadata.c',
'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/timeout_encoding.c',
'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport.c',
@ -739,8 +739,8 @@ Pod::Spec.new do |s|
'src/core/lib/transport/mdstr_hash_table.h', 'src/core/lib/transport/mdstr_hash_table.h',
'src/core/lib/transport/metadata.h', 'src/core/lib/transport/metadata.h',
'src/core/lib/transport/metadata_batch.h', 'src/core/lib/transport/metadata_batch.h',
'src/core/lib/transport/method_config.h',
'src/core/lib/transport/pid_controller.h', 'src/core/lib/transport/pid_controller.h',
'src/core/lib/transport/service_config.h',
'src/core/lib/transport/static_metadata.h', 'src/core/lib/transport/static_metadata.h',
'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/timeout_encoding.h',
'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport.h',

@ -151,6 +151,7 @@ EXPORTS
gpr_empty_slice gpr_empty_slice
grpc_slice_cmp grpc_slice_cmp
grpc_slice_str_cmp grpc_slice_str_cmp
grpc_slice_is_equivalent
grpc_slice_buffer_init grpc_slice_buffer_init
grpc_slice_buffer_destroy grpc_slice_buffer_destroy
grpc_slice_buffer_add grpc_slice_buffer_add

@ -29,7 +29,6 @@ Gem::Specification.new do |s|
s.add_dependency 'google-protobuf', '~> 3.0.2' s.add_dependency 'google-protobuf', '~> 3.0.2'
s.add_dependency 'googleauth', '~> 0.5.1' s.add_dependency 'googleauth', '~> 0.5.1'
s.add_dependency 'concurrent-ruby'
s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'bundler', '~> 1.9'
s.add_development_dependency 'facter', '~> 2.4' s.add_development_dependency 'facter', '~> 2.4'
@ -256,8 +255,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/mdstr_hash_table.h ) s.files += %w( src/core/lib/transport/mdstr_hash_table.h )
s.files += %w( src/core/lib/transport/metadata.h ) s.files += %w( src/core/lib/transport/metadata.h )
s.files += %w( src/core/lib/transport/metadata_batch.h ) s.files += %w( src/core/lib/transport/metadata_batch.h )
s.files += %w( src/core/lib/transport/method_config.h )
s.files += %w( src/core/lib/transport/pid_controller.h ) s.files += %w( src/core/lib/transport/pid_controller.h )
s.files += %w( src/core/lib/transport/service_config.h )
s.files += %w( src/core/lib/transport/static_metadata.h ) s.files += %w( src/core/lib/transport/static_metadata.h )
s.files += %w( src/core/lib/transport/timeout_encoding.h ) s.files += %w( src/core/lib/transport/timeout_encoding.h )
s.files += %w( src/core/lib/transport/transport.h ) s.files += %w( src/core/lib/transport/transport.h )
@ -449,8 +448,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/transport/mdstr_hash_table.c ) s.files += %w( src/core/lib/transport/mdstr_hash_table.c )
s.files += %w( src/core/lib/transport/metadata.c ) s.files += %w( src/core/lib/transport/metadata.c )
s.files += %w( src/core/lib/transport/metadata_batch.c ) s.files += %w( src/core/lib/transport/metadata_batch.c )
s.files += %w( src/core/lib/transport/method_config.c )
s.files += %w( src/core/lib/transport/pid_controller.c ) s.files += %w( src/core/lib/transport/pid_controller.c )
s.files += %w( src/core/lib/transport/service_config.c )
s.files += %w( src/core/lib/transport/static_metadata.c ) s.files += %w( src/core/lib/transport/static_metadata.c )
s.files += %w( src/core/lib/transport/timeout_encoding.c ) s.files += %w( src/core/lib/transport/timeout_encoding.c )
s.files += %w( src/core/lib/transport/transport.c ) s.files += %w( src/core/lib/transport/transport.c )

@ -57,6 +57,13 @@ class Channel final : public ChannelInterface,
/// \a try_to_connect is set to true, try to connect. /// \a try_to_connect is set to true, try to connect.
grpc_connectivity_state GetState(bool try_to_connect) override; grpc_connectivity_state GetState(bool try_to_connect) override;
/// Returns the LB policy name, or the empty string if not yet available.
grpc::string GetLoadBalancingPolicyName() const;
/// Returns the service config in JSON form, or the empty string if
/// not available.
grpc::string GetServiceConfigJSON() const;
private: private:
template <class InputMessage, class OutputMessage> template <class InputMessage, class OutputMessage>
friend Status BlockingUnaryCall(ChannelInterface* channel, friend Status BlockingUnaryCall(ChannelInterface* channel,

@ -93,6 +93,10 @@ class ChannelArguments {
/// grpclb LB policy will be used, regardless of what is specified here. /// grpclb LB policy will be used, regardless of what is specified here.
void SetLoadBalancingPolicyName(const grpc::string& lb_policy_name); void SetLoadBalancingPolicyName(const grpc::string& lb_policy_name);
/// Set service config in JSON form.
/// Primarily meant for use in unit tests.
void SetServiceConfigJSON(const grpc::string& service_config_json);
// Generic channel argument setters. Only for advanced use cases. // Generic channel argument setters. Only for advanced use cases.
/// Set an integer argument \a value under \a key. /// Set an integer argument \a value under \a key.
void SetInt(const grpc::string& key, int value); void SetInt(const grpc::string& key, int value);
@ -107,6 +111,15 @@ class ChannelArguments {
/// Set a textual argument \a value under \a key. /// Set a textual argument \a value under \a key.
void SetString(const grpc::string& key, const grpc::string& value); void SetString(const grpc::string& key, const grpc::string& value);
/// Return (by value) a c grpc_channel_args structure which points to
/// arguments owned by this ChannelArguments instance
grpc_channel_args c_channel_args() {
grpc_channel_args out;
out.num_args = args_.size();
out.args = args_.empty() ? NULL : &args_[0];
return out;
}
private: private:
friend class SecureChannelCredentials; friend class SecureChannelCredentials;
friend class testing::ChannelArgumentsTest; friend class testing::ChannelArgumentsTest;

@ -261,6 +261,11 @@ typedef enum grpc_call_error {
GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH
} grpc_call_error; } grpc_call_error;
/* Default send/receive message size limits in bytes. -1 for unlimited. */
/* TODO(roth) Make this match the default receive limit after next release */
#define GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH -1
#define GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024)
/* Write Flags: */ /* Write Flags: */
/** Hint that the write may be buffered and need not go out on the wire /** Hint that the write may be buffered and need not go out on the wire
immediately. GRPC is free to buffer the message until the next non-buffered immediately. GRPC is free to buffer the message until the next non-buffered
@ -478,6 +483,9 @@ typedef struct {
/* If non-NULL, will be set to point to a string indicating the LB /* If non-NULL, will be set to point to a string indicating the LB
* policy name. Caller takes ownership. */ * policy name. Caller takes ownership. */
char **lb_policy_name; char **lb_policy_name;
/* If non-NULL, will be set to point to a string containing the
* service config used by the channel in JSON form. */
char **service_config_json;
} grpc_channel_info; } grpc_channel_info;
typedef struct grpc_resource_quota grpc_resource_quota; typedef struct grpc_resource_quota grpc_resource_quota;

@ -121,6 +121,10 @@ GPRAPI grpc_slice gpr_empty_slice(void);
GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b); GPRAPI int grpc_slice_cmp(grpc_slice a, grpc_slice b);
GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b); GPRAPI int grpc_slice_str_cmp(grpc_slice a, const char *b);
/* Do two slices point at the same memory, with the same length
If a or b is inlined, actually compares data */
GPRAPI int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

@ -263,8 +263,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" />
@ -456,8 +456,8 @@
<file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/mdstr_hash_table.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/metadata_batch.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/method_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/pid_controller.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/pid_controller.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/service_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/static_metadata.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" />

@ -313,7 +313,7 @@ void GenerateServerClass(Printer *out, const ServiceDescriptor *service) {
"/// <summary>Base class for server-side implementations of " "/// <summary>Base class for server-side implementations of "
"$servicename$</summary>\n", "$servicename$</summary>\n",
"servicename", GetServiceClassName(service)); "servicename", GetServiceClassName(service));
out->Print("public abstract class $name$\n", "name", out->Print("public abstract partial class $name$\n", "name",
GetServerClassName(service)); GetServerClassName(service));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
@ -344,7 +344,7 @@ void GenerateServerClass(Printer *out, const ServiceDescriptor *service) {
void GenerateClientStub(Printer *out, const ServiceDescriptor *service) { void GenerateClientStub(Printer *out, const ServiceDescriptor *service) {
out->Print("/// <summary>Client for $servicename$</summary>\n", "servicename", out->Print("/// <summary>Client for $servicename$</summary>\n", "servicename",
GetServiceClassName(service)); GetServiceClassName(service));
out->Print("public class $name$ : ClientBase<$name$>\n", "name", out->Print("public partial class $name$ : ClientBase<$name$>\n", "name",
GetClientClassName(service)); GetClientClassName(service));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
@ -549,8 +549,8 @@ void GenerateService(Printer *out, const ServiceDescriptor *service,
bool generate_client, bool generate_server, bool generate_client, bool generate_server,
bool internal_access) { bool internal_access) {
GenerateDocCommentBody(out, service); GenerateDocCommentBody(out, service);
out->Print("$access_level$ static class $classname$\n", "access_level", out->Print("$access_level$ static partial class $classname$\n",
GetAccessLevel(internal_access), "classname", "access_level", GetAccessLevel(internal_access), "classname",
GetServiceClassName(service)); GetServiceClassName(service));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();

@ -56,7 +56,7 @@
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/transport/service_config.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
/* Client channel implementation */ /* Client channel implementation */
@ -82,30 +82,61 @@ static void *method_parameters_copy(void *value) {
return new_value; return new_value;
} }
static int method_parameters_cmp(void *value1, void *value2) {
const method_parameters *v1 = value1;
const method_parameters *v2 = value2;
const int retval = gpr_time_cmp(v1->timeout, v2->timeout);
if (retval != 0) return retval;
if (v1->wait_for_ready > v2->wait_for_ready) return 1;
if (v1->wait_for_ready < v2->wait_for_ready) return -1;
return 0;
}
static const grpc_mdstr_hash_table_vtable method_parameters_vtable = { static const grpc_mdstr_hash_table_vtable method_parameters_vtable = {
gpr_free, method_parameters_copy, method_parameters_cmp}; gpr_free, method_parameters_copy};
static void *method_config_convert_value( static void *method_parameters_create_from_json(const grpc_json *json) {
const grpc_method_config *method_config) { wait_for_ready_value wait_for_ready = WAIT_FOR_READY_UNSET;
gpr_timespec timeout = {0, 0, GPR_TIMESPAN};
for (grpc_json *field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) continue;
if (strcmp(field->key, "waitForReady") == 0) {
if (wait_for_ready != WAIT_FOR_READY_UNSET) return NULL; // Duplicate.
if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
return NULL;
}
wait_for_ready = field->type == GRPC_JSON_TRUE ? WAIT_FOR_READY_TRUE
: WAIT_FOR_READY_FALSE;
} else if (strcmp(field->key, "timeout") == 0) {
if (timeout.tv_sec > 0 || timeout.tv_nsec > 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
size_t len = strlen(field->value);
if (field->value[len - 1] != 's') return NULL;
char *buf = gpr_strdup(field->value);
buf[len - 1] = '\0'; // Remove trailing 's'.
char *decimal_point = strchr(buf, '.');
if (decimal_point != NULL) {
*decimal_point = '\0';
timeout.tv_nsec = gpr_parse_nonnegative_int(decimal_point + 1);
if (timeout.tv_nsec == -1) {
gpr_free(buf);
return NULL;
}
// There should always be exactly 3, 6, or 9 fractional digits.
int multiplier = 1;
switch (strlen(decimal_point + 1)) {
case 9:
break;
case 6:
multiplier *= 1000;
break;
case 3:
multiplier *= 1000000;
break;
default: // Unsupported number of digits.
gpr_free(buf);
return NULL;
}
timeout.tv_nsec *= multiplier;
}
timeout.tv_sec = gpr_parse_nonnegative_int(buf);
if (timeout.tv_sec == -1) return NULL;
gpr_free(buf);
}
}
method_parameters *value = gpr_malloc(sizeof(method_parameters)); method_parameters *value = gpr_malloc(sizeof(method_parameters));
const gpr_timespec *timeout = grpc_method_config_get_timeout(method_config); value->timeout = timeout;
value->timeout = timeout != NULL ? *timeout : gpr_time_0(GPR_TIMESPAN); value->wait_for_ready = wait_for_ready;
const bool *wait_for_ready =
grpc_method_config_get_wait_for_ready(method_config);
value->wait_for_ready =
wait_for_ready == NULL
? WAIT_FOR_READY_UNSET
: (wait_for_ready ? WAIT_FOR_READY_TRUE : WAIT_FOR_READY_FALSE);
return value; return value;
} }
@ -126,6 +157,8 @@ typedef struct client_channel_channel_data {
/** currently active load balancer */ /** currently active load balancer */
char *lb_policy_name; char *lb_policy_name;
grpc_lb_policy *lb_policy; grpc_lb_policy *lb_policy;
/** service config in JSON form */
char *service_config_json;
/** maps method names to method_parameters structs */ /** maps method names to method_parameters structs */
grpc_mdstr_hash_table *method_params_table; grpc_mdstr_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */ /** incoming resolver result - set by resolver.next() */
@ -232,15 +265,12 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE; grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
bool exit_idle = false; bool exit_idle = false;
grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy"); grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
char *service_config_json = NULL;
if (chand->resolver_result != NULL) { if (chand->resolver_result != NULL) {
grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory;
// Find LB policy name. // Find LB policy name.
const grpc_arg *channel_arg = const grpc_arg *channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_POLICY_NAME); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
lb_policy_name = channel_arg->value.string; lb_policy_name = channel_arg->value.string;
@ -249,7 +279,7 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
// assume that we should use the grpclb policy, regardless of what the // assume that we should use the grpclb policy, regardless of what the
// resolver actually specified. // resolver actually specified.
channel_arg = channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_ADDRESSES); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = channel_arg->value.pointer.p; grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
@ -274,7 +304,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
// Use pick_first if nothing was specified and we didn't select grpclb // Use pick_first if nothing was specified and we didn't select grpclb
// above. // above.
if (lb_policy_name == NULL) lb_policy_name = "pick_first"; if (lb_policy_name == NULL) lb_policy_name = "pick_first";
// Instantiate LB policy.
grpc_lb_policy_args lb_policy_args;
lb_policy_args.args = chand->resolver_result;
lb_policy_args.client_channel_factory = chand->client_channel_factory;
lb_policy = lb_policy =
grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args); grpc_lb_policy_create(exec_ctx, lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) { if (lb_policy != NULL) {
@ -283,13 +316,20 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
state = state =
grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error); grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
} }
// Find service config.
channel_arg = channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_SERVICE_CONFIG); grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
method_params_table = grpc_method_config_table_convert( service_config_json = gpr_strdup(channel_arg->value.string);
(grpc_method_config_table *)channel_arg->value.pointer.p, grpc_service_config *service_config =
method_config_convert_value, &method_parameters_vtable); grpc_service_config_create(service_config_json);
if (service_config != NULL) {
method_params_table = grpc_service_config_create_method_config_table(
service_config, method_parameters_create_from_json,
&method_parameters_vtable);
grpc_service_config_destroy(service_config);
}
} }
// Before we clean up, save a copy of lb_policy_name, since it might // Before we clean up, save a copy of lb_policy_name, since it might
// be pointing to data inside chand->resolver_result. // be pointing to data inside chand->resolver_result.
@ -311,6 +351,10 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
} }
old_lb_policy = chand->lb_policy; old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy; chand->lb_policy = lb_policy;
if (service_config_json != NULL) {
gpr_free(chand->service_config_json);
chand->service_config_json = service_config_json;
}
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(chand->method_params_table); grpc_mdstr_hash_table_unref(chand->method_params_table);
} }
@ -446,6 +490,11 @@ static void cc_get_channel_info(grpc_exec_ctx *exec_ctx,
? NULL ? NULL
: gpr_strdup(chand->lb_policy_name); : gpr_strdup(chand->lb_policy_name);
} }
if (info->service_config_json != NULL) {
*info->service_config_json = chand->service_config_json == NULL
? NULL
: gpr_strdup(chand->service_config_json);
}
gpr_mu_unlock(&chand->mu); gpr_mu_unlock(&chand->mu);
} }
@ -489,6 +538,7 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel"); GRPC_LB_POLICY_UNREF(exec_ctx, chand->lb_policy, "channel");
} }
gpr_free(chand->lb_policy_name); gpr_free(chand->lb_policy_name);
gpr_free(chand->service_config_json);
if (chand->method_params_table != NULL) { if (chand->method_params_table != NULL) {
grpc_mdstr_hash_table_unref(chand->method_params_table); grpc_mdstr_hash_table_unref(chand->method_params_table);
} }

@ -35,6 +35,8 @@
#include <string.h> #include <string.h>
#include "src/core/lib/support/string.h"
#define MAX_POLICIES 10 #define MAX_POLICIES 10
static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES]; static grpc_lb_policy_factory *g_all_of_the_lb_policies[MAX_POLICIES];
@ -52,8 +54,8 @@ void grpc_lb_policy_registry_shutdown(void) {
void grpc_register_lb_policy(grpc_lb_policy_factory *factory) { void grpc_register_lb_policy(grpc_lb_policy_factory *factory) {
int i; int i;
for (i = 0; i < g_number_of_lb_policies; i++) { for (i = 0; i < g_number_of_lb_policies; i++) {
GPR_ASSERT(0 != strcmp(factory->vtable->name, GPR_ASSERT(0 != gpr_stricmp(factory->vtable->name,
g_all_of_the_lb_policies[i]->vtable->name)); g_all_of_the_lb_policies[i]->vtable->name));
} }
GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES); GPR_ASSERT(g_number_of_lb_policies != MAX_POLICIES);
grpc_lb_policy_factory_ref(factory); grpc_lb_policy_factory_ref(factory);
@ -66,7 +68,7 @@ static grpc_lb_policy_factory *lookup_factory(const char *name) {
if (name == NULL) return NULL; if (name == NULL) return NULL;
for (i = 0; i < g_number_of_lb_policies; i++) { for (i = 0; i < g_number_of_lb_policies; i++) {
if (0 == strcmp(name, g_all_of_the_lb_policies[i]->vtable->name)) { if (0 == gpr_stricmp(name, g_all_of_the_lb_policies[i]->vtable->name)) {
return g_all_of_the_lb_policies[i]; return g_all_of_the_lb_policies[i];
} }
} }

@ -119,9 +119,9 @@ struct grpc_subchannel {
gpr_mu mu; gpr_mu mu;
/** have we seen a disconnection? */ /** have we seen a disconnection? */
int disconnected; bool disconnected;
/** are we connecting */ /** are we connecting */
int connecting; bool connecting;
/** connectivity state tracking */ /** connectivity state tracking */
grpc_connectivity_state_tracker state_tracker; grpc_connectivity_state_tracker state_tracker;
@ -132,7 +132,9 @@ struct grpc_subchannel {
/** backoff state */ /** backoff state */
gpr_backoff backoff_state; gpr_backoff backoff_state;
/** do we have an active alarm? */ /** do we have an active alarm? */
int have_alarm; bool have_alarm;
/** have we started the backoff loop */
bool backoff_begun;
/** our alarm */ /** our alarm */
grpc_timer alarm; grpc_timer alarm;
}; };
@ -264,7 +266,7 @@ static void disconnect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
grpc_subchannel_index_unregister(exec_ctx, c->key, c); grpc_subchannel_index_unregister(exec_ctx, c->key, c);
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->disconnected); GPR_ASSERT(!c->disconnected);
c->disconnected = 1; c->disconnected = true;
grpc_connector_shutdown(exec_ctx, c->connector); grpc_connector_shutdown(exec_ctx, c->connector);
con = GET_CONNECTED_SUBCHANNEL(c, no_barrier); con = GET_CONNECTED_SUBCHANNEL(c, no_barrier);
if (con != NULL) { if (con != NULL) {
@ -370,7 +372,8 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
return grpc_subchannel_index_register(exec_ctx, key, c); return grpc_subchannel_index_register(exec_ctx, key, c);
} }
static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) { static void continue_connect_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c) {
grpc_connect_in_args args; grpc_connect_in_args args;
args.interested_parties = c->pollset_set; args.interested_parties = c->pollset_set;
@ -386,12 +389,6 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
&c->connected); &c->connected);
} }
static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
c->next_attempt =
gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
}
grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c, grpc_connectivity_state grpc_subchannel_check_connectivity(grpc_subchannel *c,
grpc_error **error) { grpc_error **error) {
grpc_connectivity_state state; grpc_connectivity_state state;
@ -418,6 +415,73 @@ static void on_external_state_watcher_done(grpc_exec_ctx *exec_ctx, void *arg,
follow_up->cb(exec_ctx, follow_up->cb_arg, error); follow_up->cb(exec_ctx, follow_up->cb_arg, error);
} }
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
c->have_alarm = false;
if (c->disconnected) {
error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
} else {
GRPC_ERROR_REF(error);
}
if (error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
c->next_attempt =
gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect_locked(exec_ctx, c);
gpr_mu_unlock(&c->mu);
} else {
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
GRPC_ERROR_UNREF(error);
}
static void maybe_start_connecting_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c) {
if (c->disconnected) {
/* Don't try to connect if we're already disconnected */
return;
}
if (c->connecting) {
/* Already connecting: don't restart */
return;
}
if (GET_CONNECTED_SUBCHANNEL(c, no_barrier) != NULL) {
/* Already connected: don't restart */
return;
}
if (!grpc_connectivity_state_has_watchers(&c->state_tracker)) {
/* Nobody is interested in connecting: so don't just yet */
return;
}
c->connecting = true;
GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
if (!c->backoff_begun) {
c->backoff_begun = true;
c->next_attempt = gpr_backoff_begin(&c->backoff_state, now);
continue_connect_locked(exec_ctx, c);
} else {
GPR_ASSERT(!c->have_alarm);
c->have_alarm = true;
gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
0) {
gpr_log(GPR_INFO, "Retry immediately");
} else {
gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
time_til_next.tv_sec, time_til_next.tv_nsec);
}
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
}
}
void grpc_subchannel_notify_on_state_change( void grpc_subchannel_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_subchannel *c, grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
grpc_pollset_set *interested_parties, grpc_connectivity_state *state, grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
@ -449,13 +513,9 @@ void grpc_subchannel_notify_on_state_change(
w->next = &c->root_external_state_watcher; w->next = &c->root_external_state_watcher;
w->prev = w->next->prev; w->prev = w->next->prev;
w->next->prev = w->prev->next = w; w->next->prev = w->prev->next = w;
if (grpc_connectivity_state_notify_on_state_change( grpc_connectivity_state_notify_on_state_change(exec_ctx, &c->state_tracker,
exec_ctx, &c->state_tracker, state, &w->closure)) { state, &w->closure);
c->connecting = 1; maybe_start_connecting_locked(exec_ctx, c);
/* released by connection */
GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
start_connect(exec_ctx, c);
}
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
} }
} }
@ -575,7 +635,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
Re-evaluate if we really need this. */ Re-evaluate if we really need this. */
gpr_atm_full_barrier(); gpr_atm_full_barrier();
GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con)); GPR_ASSERT(gpr_atm_rel_cas(&c->connected_subchannel, 0, (gpr_atm)con));
c->connecting = 0;
/* setup subchannel watching connected subchannel for changes; subchannel /* setup subchannel watching connected subchannel for changes; subchannel
ref ref
@ -592,28 +651,6 @@ static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
GRPC_ERROR_NONE, "connected"); GRPC_ERROR_NONE, "connected");
} }
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
c->have_alarm = 0;
if (c->disconnected) {
error = GRPC_ERROR_CREATE_REFERENCING("Disconnected", &error, 1);
} else {
GRPC_ERROR_REF(error);
}
if (error == GRPC_ERROR_NONE) {
gpr_log(GPR_INFO, "Failed to connect to channel, retrying");
c->next_attempt =
gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
gpr_mu_unlock(&c->mu);
} else {
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
GRPC_ERROR_UNREF(error);
}
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg, static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
grpc_subchannel *c = arg; grpc_subchannel *c = arg;
@ -621,35 +658,28 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_SUBCHANNEL_WEAK_REF(c, "connected"); GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
gpr_mu_lock(&c->mu); gpr_mu_lock(&c->mu);
c->connecting = false;
if (c->connecting_result.transport != NULL) { if (c->connecting_result.transport != NULL) {
publish_transport_locked(exec_ctx, c); publish_transport_locked(exec_ctx, c);
} else if (c->disconnected) { } else if (c->disconnected) {
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
} else { } else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1;
grpc_connectivity_state_set( grpc_connectivity_state_set(
exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE, exec_ctx, &c->state_tracker, GRPC_CHANNEL_TRANSIENT_FAILURE,
grpc_error_set_int( grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1), GRPC_ERROR_CREATE_REFERENCING("Connect Failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE),
"connect_failed"); "connect_failed");
gpr_timespec time_til_next = gpr_time_sub(c->next_attempt, now);
const char *errmsg = grpc_error_string(error); const char *errmsg = grpc_error_string(error);
gpr_log(GPR_INFO, "Connect failed: %s", errmsg); gpr_log(GPR_INFO, "Connect failed: %s", errmsg);
if (gpr_time_cmp(time_til_next, gpr_time_0(time_til_next.clock_type)) <=
0) {
gpr_log(GPR_INFO, "Retry immediately");
} else {
gpr_log(GPR_INFO, "Retry in %" PRId64 ".%09d seconds",
time_til_next.tv_sec, time_til_next.tv_nsec);
}
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
grpc_error_free_string(errmsg); grpc_error_free_string(errmsg);
maybe_start_connecting_locked(exec_ctx, c);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
} }
gpr_mu_unlock(&c->mu); gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting"); GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connected");
grpc_channel_args_destroy(delete_channel_args); grpc_channel_args_destroy(delete_channel_args);
} }

@ -182,18 +182,24 @@ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg,
NULL); NULL);
if (wc_arg->rr_policy != NULL) { if (wc_arg->rr_policy != NULL) {
/* if target is NULL, no pick has been made by the RR policy (eg, all /* if *target is NULL, no pick has been made by the RR policy (eg, all
* addresses failed to connect). There won't be any user_data/token * addresses failed to connect). There won't be any user_data/token
* available */ * available */
if (wc_arg->target != NULL) { if (*wc_arg->target != NULL) {
GPR_ASSERT(wc_arg->lb_token != NULL); if (wc_arg->lb_token != NULL) {
initial_metadata_add_lb_token(wc_arg->initial_metadata, initial_metadata_add_lb_token(wc_arg->initial_metadata,
wc_arg->lb_token_mdelem_storage, wc_arg->lb_token_mdelem_storage,
GRPC_MDELEM_REF(wc_arg->lb_token)); GRPC_MDELEM_REF(wc_arg->lb_token));
} else {
gpr_log(GPR_ERROR,
"No LB token for connected subchannel pick %p (from RR "
"instance %p).",
(void *)*wc_arg->target, (void *)wc_arg->rr_policy);
abort();
}
} }
if (grpc_lb_glb_trace) { if (grpc_lb_glb_trace) {
gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy);
(intptr_t)wc_arg->rr_policy);
} }
GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure");
} }
@ -411,7 +417,7 @@ static void parse_server(const grpc_grpclb_server *server,
} }
/* Returns addresses extracted from \a serverlist. */ /* Returns addresses extracted from \a serverlist. */
static grpc_lb_addresses *process_serverlist( static grpc_lb_addresses *process_serverlist_locked(
const grpc_grpclb_serverlist *serverlist) { const grpc_grpclb_serverlist *serverlist) {
size_t num_valid = 0; size_t num_valid = 0;
/* first pass: count how many are valid in order to allocate the necessary /* first pass: count how many are valid in order to allocate the necessary
@ -451,10 +457,12 @@ static grpc_lb_addresses *process_serverlist(
user_data = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_LB_TOKEN, user_data = grpc_mdelem_from_metadata_strings(GRPC_MDSTR_LB_TOKEN,
lb_token_mdstr); lb_token_mdstr);
} else { } else {
gpr_log(GPR_ERROR, char *uri = grpc_sockaddr_to_uri(&addr);
gpr_log(GPR_INFO,
"Missing LB token for backend address '%s'. The empty token will " "Missing LB token for backend address '%s'. The empty token will "
"be used instead", "be used instead",
grpc_sockaddr_to_uri(&addr)); uri);
gpr_free(uri);
user_data = GRPC_MDELEM_LB_TOKEN_EMPTY; user_data = GRPC_MDELEM_LB_TOKEN_EMPTY;
} }
@ -467,6 +475,68 @@ static grpc_lb_addresses *process_serverlist(
return lb_addresses; return lb_addresses;
} }
/* returns true if the new RR policy should replace the current one, if any */
static bool update_lb_connectivity_status_locked(
grpc_exec_ctx *exec_ctx, glb_lb_policy *glb_policy,
grpc_connectivity_state new_rr_state, grpc_error *new_rr_state_error) {
grpc_error *curr_state_error;
const grpc_connectivity_state curr_glb_state = grpc_connectivity_state_check(
&glb_policy->state_tracker, &curr_state_error);
/* The new connectivity status is a function of the previous one and the new
* input coming from the status of the RR policy.
*
* current state (grpclb's)
* |
* v || I | C | R | TF | SD | <- new state (RR's)
* ===++====+=====+=====+======+======+
* I || I | C | R | [I] | [I] |
* ---++----+-----+-----+------+------+
* C || I | C | R | [C] | [C] |
* ---++----+-----+-----+------+------+
* R || I | C | R | [R] | [R] |
* ---++----+-----+-----+------+------+
* TF || I | C | R | [TF] | [TF] |
* ---++----+-----+-----+------+------+
* SD || NA | NA | NA | NA | NA | (*)
* ---++----+-----+-----+------+------+
*
* A [STATE] indicates that the old RR policy is kept. In those cases, STATE
* is the current state of grpclb, which is left untouched.
*
* In summary, if the new state is TRANSIENT_FAILURE or SHUTDOWN, stick to
* the previous RR instance.
*
* Note that the status is never updated to SHUTDOWN as a result of calling
* this function. Only glb_shutdown() has the power to set that state.
*
* (*) This function mustn't be called during shutting down. */
GPR_ASSERT(curr_glb_state != GRPC_CHANNEL_SHUTDOWN);
switch (new_rr_state) {
case GRPC_CHANNEL_TRANSIENT_FAILURE:
case GRPC_CHANNEL_SHUTDOWN:
GPR_ASSERT(new_rr_state_error != GRPC_ERROR_NONE);
return false; /* don't replace the RR policy */
case GRPC_CHANNEL_INIT:
case GRPC_CHANNEL_IDLE:
case GRPC_CHANNEL_CONNECTING:
case GRPC_CHANNEL_READY:
GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE);
}
if (grpc_lb_glb_trace) {
gpr_log(GPR_INFO,
"Setting grpclb's state to %s from new RR policy %p state.",
grpc_connectivity_state_name(new_rr_state),
(void *)glb_policy->rr_policy);
}
grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker,
new_rr_state, GRPC_ERROR_REF(new_rr_state_error),
"update_lb_connectivity_status_locked");
return true;
}
/* perform a pick over \a rr_policy. Given that a pick can return immediately /* perform a pick over \a rr_policy. Given that a pick can return immediately
* (ignoring its completion callback) we need to perform the cleanups this * (ignoring its completion callback) we need to perform the cleanups this
* callback would be otherwise resposible for */ * callback would be otherwise resposible for */
@ -508,7 +578,7 @@ static grpc_lb_policy *create_rr_locked(
grpc_lb_policy_args args; grpc_lb_policy_args args;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.client_channel_factory = glb_policy->cc_factory; args.client_channel_factory = glb_policy->cc_factory;
grpc_lb_addresses *addresses = process_serverlist(serverlist); grpc_lb_addresses *addresses = process_serverlist_locked(serverlist);
// Replace the LB addresses in the channel args that we pass down to // Replace the LB addresses in the channel args that we pass down to
// the subchannel. // the subchannel.
@ -529,49 +599,84 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error); grpc_error *error);
/* glb_policy->rr_policy may be NULL (initial handover) */ /* glb_policy->rr_policy may be NULL (initial handover) */
static void rr_handover_locked(grpc_exec_ctx *exec_ctx, static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
glb_lb_policy *glb_policy, grpc_error *error) { glb_lb_policy *glb_policy) {
GPR_ASSERT(glb_policy->serverlist != NULL && GPR_ASSERT(glb_policy->serverlist != NULL &&
glb_policy->serverlist->num_servers > 0); glb_policy->serverlist->num_servers > 0);
if (glb_policy->shutting_down) return;
grpc_lb_policy *new_rr_policy =
create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy);
if (new_rr_policy == NULL) {
gpr_log(GPR_ERROR,
"Failure creating a RoundRobin policy for serverlist update with "
"%lu entries. The previous RR instance (%p), if any, will continue "
"to be used. Future updates from the LB will attempt to create new "
"instances.",
(unsigned long)glb_policy->serverlist->num_servers,
(void *)glb_policy->rr_policy);
return;
}
grpc_error *new_rr_state_error = NULL;
const grpc_connectivity_state new_rr_state =
grpc_lb_policy_check_connectivity(exec_ctx, new_rr_policy,
&new_rr_state_error);
/* Connectivity state is a function of the new RR policy just created */
const bool replace_old_rr = update_lb_connectivity_status_locked(
exec_ctx, glb_policy, new_rr_state, new_rr_state_error);
if (!replace_old_rr) {
/* dispose of the new RR policy that won't be used after all */
GRPC_LB_POLICY_UNREF(exec_ctx, new_rr_policy, "rr_handover_no_replace");
if (grpc_lb_glb_trace) {
gpr_log(GPR_INFO,
"Keeping old RR policy (%p) despite new serverlist: new RR "
"policy was in %s connectivity state.",
(void *)glb_policy->rr_policy,
grpc_connectivity_state_name(new_rr_state));
}
return;
}
if (grpc_lb_glb_trace) { if (grpc_lb_glb_trace) {
gpr_log(GPR_INFO, "RR handover. Old RR: %p", (void *)glb_policy->rr_policy); gpr_log(GPR_INFO, "Created RR policy (%p) to replace old RR (%p)",
(void *)new_rr_policy, (void *)glb_policy->rr_policy);
} }
if (glb_policy->rr_policy != NULL) { if (glb_policy->rr_policy != NULL) {
/* if we are phasing out an existing RR instance, unref it. */ /* if we are phasing out an existing RR instance, unref it. */
GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "rr_handover"); GRPC_LB_POLICY_UNREF(exec_ctx, glb_policy->rr_policy, "rr_handover");
} }
glb_policy->rr_policy = /* Finally update the RR policy to the newly created one */
create_rr_locked(exec_ctx, glb_policy->serverlist, glb_policy); glb_policy->rr_policy = new_rr_policy;
if (grpc_lb_glb_trace) {
gpr_log(GPR_INFO, "Created RR policy (%p)", (void *)glb_policy->rr_policy);
}
GPR_ASSERT(glb_policy->rr_policy != NULL); /* Add the gRPC LB's interested_parties pollset_set to that of the newly
* created RR policy. This will make the RR policy progress upon activity on
* gRPC LB, which in turn is tied to the application's call */
grpc_pollset_set_add_pollset_set(exec_ctx, grpc_pollset_set_add_pollset_set(exec_ctx,
glb_policy->rr_policy->interested_parties, glb_policy->rr_policy->interested_parties,
glb_policy->base.interested_parties); glb_policy->base.interested_parties);
/* Allocate the data for the tracking of the new RR policy's connectivity.
* It'll be deallocated in glb_rr_connectivity_changed() */
rr_connectivity_data *rr_connectivity = rr_connectivity_data *rr_connectivity =
gpr_malloc(sizeof(rr_connectivity_data)); gpr_malloc(sizeof(rr_connectivity_data));
memset(rr_connectivity, 0, sizeof(rr_connectivity_data)); memset(rr_connectivity, 0, sizeof(rr_connectivity_data));
grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed, grpc_closure_init(&rr_connectivity->on_change, glb_rr_connectivity_changed,
rr_connectivity); rr_connectivity);
rr_connectivity->glb_policy = glb_policy; rr_connectivity->glb_policy = glb_policy;
rr_connectivity->state = grpc_lb_policy_check_connectivity( rr_connectivity->state = new_rr_state;
exec_ctx, glb_policy->rr_policy, &error);
grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, /* Subscribe to changes to the connectivity of the new RR */
rr_connectivity->state, GRPC_ERROR_REF(error),
"rr_handover");
/* subscribe */
GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb"); GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "rr_connectivity_cb");
grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy, grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
&rr_connectivity->state, &rr_connectivity->state,
&rr_connectivity->on_change); &rr_connectivity->on_change);
grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy); grpc_lb_policy_exit_idle(exec_ctx, glb_policy->rr_policy);
/* flush pending ops */ /* Update picks and pings in wait */
pending_pick *pp; pending_pick *pp;
while ((pp = glb_policy->pending_picks)) { while ((pp = glb_policy->pending_picks)) {
glb_policy->pending_picks = pp->next; glb_policy->pending_picks = pp->next;
@ -602,28 +707,36 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx,
static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg, static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
/* If shutdown or error free the arg. Rely on the rest of the code to set the rr_connectivity_data *rr_connectivity = arg;
* right grpclb status. */ glb_lb_policy *glb_policy = rr_connectivity->glb_policy;
rr_connectivity_data *rr_conn_data = arg;
glb_lb_policy *glb_policy = rr_conn_data->glb_policy;
gpr_mu_lock(&glb_policy->mu);
if (rr_conn_data->state != GRPC_CHANNEL_SHUTDOWN && gpr_mu_lock(&glb_policy->mu);
!glb_policy->shutting_down) { const bool shutting_down = glb_policy->shutting_down;
/* RR not shutting down. Mimic the RR's policy state */ bool unref_needed = false;
grpc_connectivity_state_set(exec_ctx, &glb_policy->state_tracker, GRPC_ERROR_REF(error);
rr_conn_data->state, GRPC_ERROR_REF(error),
"rr_connectivity_cb"); if (rr_connectivity->state == GRPC_CHANNEL_SHUTDOWN || shutting_down) {
/* resubscribe. Reuse the "rr_connectivity_cb" weak ref. */ /* RR policy shutting down. Don't renew subscription and free the arg of
* this callback. In addition we need to stash away the current policy to
* be UNREF'd after releasing the lock. Otherwise, if the UNREF is the last
* one, the policy would be destroyed, alongside the lock, which would
* result in a use-after-free */
unref_needed = true;
gpr_free(rr_connectivity);
} else { /* rr state != SHUTDOWN && !shutting down: biz as usual */
update_lb_connectivity_status_locked(exec_ctx, glb_policy,
rr_connectivity->state, error);
/* Resubscribe. Reuse the "rr_connectivity_cb" weak ref. */
grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy, grpc_lb_policy_notify_on_state_change(exec_ctx, glb_policy->rr_policy,
&rr_conn_data->state, &rr_connectivity->state,
&rr_conn_data->on_change); &rr_connectivity->on_change);
} else { }
gpr_mu_unlock(&glb_policy->mu);
if (unref_needed) {
GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base,
"rr_connectivity_cb"); "rr_connectivity_cb");
gpr_free(rr_conn_data);
} }
gpr_mu_unlock(&glb_policy->mu); GRPC_ERROR_UNREF(error);
} }
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
@ -768,7 +881,6 @@ static void glb_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
* while holding glb_policy->mu: lb_on_server_status_received, invoked due to * while holding glb_policy->mu: lb_on_server_status_received, invoked due to
* the cancel, needs to acquire that same lock */ * the cancel, needs to acquire that same lock */
grpc_call *lb_call = glb_policy->lb_call; grpc_call *lb_call = glb_policy->lb_call;
glb_policy->lb_call = NULL;
gpr_mu_unlock(&glb_policy->mu); gpr_mu_unlock(&glb_policy->mu);
/* glb_policy->lb_call and this local lb_call must be consistent at this point /* glb_policy->lb_call and this local lb_call must be consistent at this point
@ -1126,15 +1238,18 @@ static void lb_on_response_received(grpc_exec_ctx *exec_ctx, void *arg,
gpr_log(GPR_INFO, gpr_log(GPR_INFO,
"Incoming server list identical to current, ignoring."); "Incoming server list identical to current, ignoring.");
} }
grpc_grpclb_destroy_serverlist(serverlist);
} else { /* new serverlist */ } else { /* new serverlist */
if (glb_policy->serverlist != NULL) { if (glb_policy->serverlist != NULL) {
/* dispose of the old serverlist */ /* dispose of the old serverlist */
grpc_grpclb_destroy_serverlist(glb_policy->serverlist); grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
} }
/* and update the copy in the glb_lb_policy instance */ /* and update the copy in the glb_lb_policy instance. This serverlist
* instance will be destroyed either upon the next update or in
* glb_destroy() */
glb_policy->serverlist = serverlist; glb_policy->serverlist = serverlist;
rr_handover_locked(exec_ctx, glb_policy, error); rr_handover_locked(exec_ctx, glb_policy);
} }
} else { } else {
if (grpc_lb_glb_trace) { if (grpc_lb_glb_trace) {

@ -956,6 +956,16 @@ static void complete_fetch(grpc_exec_ctx *exec_ctx, void *gs,
static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id,
bool is_client, bool is_initial) {
for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail;
md = md->next) {
gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->md->key),
grpc_mdstr_as_c_string(md->md->value));
}
}
static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
grpc_error *error_ignored) { grpc_error *error_ignored) {
GPR_TIMER_BEGIN("perform_stream_op_locked", 0); GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
@ -969,6 +979,12 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str, gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str,
op->on_complete); op->on_complete);
gpr_free(str); gpr_free(str);
if (op->send_initial_metadata) {
log_metadata(op->send_initial_metadata, s->id, t->is_client, true);
}
if (op->send_trailing_metadata) {
log_metadata(op->send_trailing_metadata, s->id, t->is_client, false);
}
} }
grpc_closure *on_complete = op->on_complete; grpc_closure *on_complete = op->on_complete;

@ -36,6 +36,7 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include <string.h> #include <string.h>
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport_impl.h" #include "src/core/lib/transport/transport_impl.h"
@ -56,6 +57,7 @@ typedef struct call_data {
grpc_linked_mdelem payload_bin; grpc_linked_mdelem payload_bin;
grpc_metadata_batch *recv_initial_metadata; grpc_metadata_batch *recv_initial_metadata;
grpc_metadata_batch *recv_trailing_metadata;
uint8_t *payload_bytes; uint8_t *payload_bytes;
/* Vars to read data off of send_message */ /* Vars to read data off of send_message */
@ -69,14 +71,16 @@ typedef struct call_data {
bool send_message_blocked; bool send_message_blocked;
/** Closure to call when finished with the hc_on_recv hook */ /** Closure to call when finished with the hc_on_recv hook */
grpc_closure *on_done_recv; grpc_closure *on_done_recv_initial_metadata;
grpc_closure *on_done_recv_trailing_metadata;
grpc_closure *on_complete; grpc_closure *on_complete;
grpc_closure *post_send; grpc_closure *post_send;
/** Receive closures are chained: we inject this closure as the 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 up-call on transport_op, and remember to call our on_done_recv member
after handling it. */ after handling it. */
grpc_closure hc_on_recv; grpc_closure hc_on_recv_initial_metadata;
grpc_closure hc_on_recv_trailing_metadata;
grpc_closure hc_on_complete; grpc_closure hc_on_complete;
grpc_closure got_slice; grpc_closure got_slice;
grpc_closure send_done; grpc_closure send_done;
@ -106,6 +110,16 @@ static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
grpc_call_element_send_close_with_message(a->exec_ctx, a->elem, grpc_call_element_send_close_with_message(a->exec_ctx, a->elem,
GRPC_STATUS_CANCELLED, &message); GRPC_STATUS_CANCELLED, &message);
return NULL; return NULL;
} else if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
grpc_slice pct_decoded_msg =
grpc_permissive_percent_decode_slice(md->value->slice);
if (grpc_slice_is_equivalent(pct_decoded_msg, md->value->slice)) {
grpc_slice_unref(pct_decoded_msg);
return md;
} else {
return grpc_mdelem_from_metadata_strings(
GRPC_MDSTR_GRPC_MESSAGE, grpc_mdstr_from_slice(pct_decoded_msg));
}
} else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { } else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) {
return NULL; return NULL;
} else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
@ -129,8 +143,8 @@ static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) {
return md; return md;
} }
static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data, static void hc_on_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
grpc_error *error) { void *user_data, grpc_error *error) {
grpc_call_element *elem = user_data; grpc_call_element *elem = user_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
client_recv_filter_args a; client_recv_filter_args a;
@ -138,7 +152,21 @@ static void hc_on_recv(grpc_exec_ctx *exec_ctx, void *user_data,
a.exec_ctx = exec_ctx; a.exec_ctx = exec_ctx;
grpc_metadata_batch_filter(calld->recv_initial_metadata, client_recv_filter, grpc_metadata_batch_filter(calld->recv_initial_metadata, client_recv_filter,
&a); &a);
calld->on_done_recv->cb(exec_ctx, calld->on_done_recv->cb_arg, error); grpc_closure_run(exec_ctx, calld->on_done_recv_initial_metadata,
GRPC_ERROR_REF(error));
}
static void hc_on_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
void *user_data, grpc_error *error) {
grpc_call_element *elem = user_data;
call_data *calld = elem->call_data;
client_recv_filter_args a;
a.elem = elem;
a.exec_ctx = exec_ctx;
grpc_metadata_batch_filter(calld->recv_trailing_metadata, client_recv_filter,
&a);
grpc_closure_run(exec_ctx, calld->on_done_recv_trailing_metadata,
GRPC_ERROR_REF(error));
} }
static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data, static void hc_on_complete(grpc_exec_ctx *exec_ctx, void *user_data,
@ -217,12 +245,15 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
message, and the payload is below the size threshold, and all the data message, and the payload is below the size threshold, and all the data
for this request is immediately available. */ for this request is immediately available. */
grpc_mdelem *method = GRPC_MDELEM_METHOD_POST; grpc_mdelem *method = GRPC_MDELEM_METHOD_POST;
calld->send_message_blocked = false;
if ((op->send_initial_metadata_flags & if ((op->send_initial_metadata_flags &
GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) && GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) &&
op->send_message != NULL && op->send_message != NULL &&
op->send_message->length < channeld->max_payload_size_for_get) { op->send_message->length < channeld->max_payload_size_for_get) {
method = GRPC_MDELEM_METHOD_GET; method = GRPC_MDELEM_METHOD_GET;
/* The following write to calld->send_message_blocked isn't racy with
reads in hc_start_transport_op (which deals with SEND_MESSAGE ops) because
being here means ops->send_message is not NULL, which is primarily
guarding the read there. */
calld->send_message_blocked = true; calld->send_message_blocked = true;
} else if (op->send_initial_metadata_flags & } else if (op->send_initial_metadata_flags &
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) {
@ -281,8 +312,15 @@ static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
if (op->recv_initial_metadata != NULL) { if (op->recv_initial_metadata != NULL) {
/* substitute our callback for the higher callback */ /* substitute our callback for the higher callback */
calld->recv_initial_metadata = op->recv_initial_metadata; calld->recv_initial_metadata = op->recv_initial_metadata;
calld->on_done_recv = op->recv_initial_metadata_ready; calld->on_done_recv_initial_metadata = op->recv_initial_metadata_ready;
op->recv_initial_metadata_ready = &calld->hc_on_recv; op->recv_initial_metadata_ready = &calld->hc_on_recv_initial_metadata;
}
if (op->recv_trailing_metadata != NULL) {
/* substitute our callback for the higher callback */
calld->recv_trailing_metadata = op->recv_trailing_metadata;
calld->on_done_recv_trailing_metadata = op->on_complete;
op->on_complete = &calld->hc_on_recv_trailing_metadata;
} }
} }
@ -296,8 +334,7 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
if (op->send_message != NULL && calld->send_message_blocked) { if (op->send_message != NULL && calld->send_message_blocked) {
/* Don't forward the op. send_message contains slices that aren't ready /* Don't forward the op. send_message contains slices that aren't ready
yet. The call will be forwarded by the op_complete of slice read call. yet. The call will be forwarded by the op_complete of slice read call. */
*/
} else { } else {
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(exec_ctx, elem, op);
} }
@ -308,11 +345,16 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
calld->on_done_recv = NULL; calld->on_done_recv_initial_metadata = NULL;
calld->on_done_recv_trailing_metadata = NULL;
calld->on_complete = NULL; calld->on_complete = NULL;
calld->payload_bytes = NULL; calld->payload_bytes = NULL;
calld->send_message_blocked = false;
grpc_slice_buffer_init(&calld->slices); grpc_slice_buffer_init(&calld->slices);
grpc_closure_init(&calld->hc_on_recv, hc_on_recv, elem); grpc_closure_init(&calld->hc_on_recv_initial_metadata,
hc_on_recv_initial_metadata, elem);
grpc_closure_init(&calld->hc_on_recv_trailing_metadata,
hc_on_recv_trailing_metadata, elem);
grpc_closure_init(&calld->hc_on_complete, hc_on_complete, elem); grpc_closure_init(&calld->hc_on_complete, hc_on_complete, elem);
grpc_closure_init(&calld->got_slice, got_slice, elem); grpc_closure_init(&calld->got_slice, got_slice, elem);
grpc_closure_init(&calld->send_done, send_done, elem); grpc_closure_init(&calld->send_done, send_done, elem);

@ -37,6 +37,7 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <string.h> #include <string.h>
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE "application/grpc"
@ -86,6 +87,23 @@ typedef struct {
grpc_exec_ctx *exec_ctx; grpc_exec_ctx *exec_ctx;
} server_filter_args; } server_filter_args;
static grpc_mdelem *server_filter_outgoing_metadata(void *user_data,
grpc_mdelem *md) {
if (md->key == GRPC_MDSTR_GRPC_MESSAGE) {
grpc_slice pct_encoded_msg = grpc_percent_encode_slice(
md->value->slice, grpc_compatible_percent_encoding_unreserved_bytes);
if (grpc_slice_is_equivalent(pct_encoded_msg, md->value->slice)) {
grpc_slice_unref(pct_encoded_msg);
return md;
} else {
return grpc_mdelem_from_metadata_strings(
GRPC_MDSTR_GRPC_MESSAGE, grpc_mdstr_from_slice(pct_encoded_msg));
}
} else {
return md;
}
}
static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) { static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
server_filter_args *a = user_data; server_filter_args *a = user_data;
grpc_call_element *elem = a->elem; grpc_call_element *elem = a->elem;
@ -254,7 +272,7 @@ static void hs_recv_message_ready(grpc_exec_ctx *exec_ctx, void *user_data,
} }
} }
static void hs_mutate_op(grpc_call_element *elem, static void hs_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
@ -290,6 +308,12 @@ static void hs_mutate_op(grpc_call_element *elem,
op->on_complete = &calld->hs_on_complete; op->on_complete = &calld->hs_on_complete;
} }
} }
if (op->send_trailing_metadata) {
server_filter_args a = {elem, exec_ctx};
grpc_metadata_batch_filter(op->send_trailing_metadata,
server_filter_outgoing_metadata, &a);
}
} }
static void hs_start_transport_op(grpc_exec_ctx *exec_ctx, static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
@ -297,7 +321,7 @@ static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_transport_stream_op *op) { grpc_transport_stream_op *op) {
GRPC_CALL_LOG_OP(GPR_INFO, elem, op); GRPC_CALL_LOG_OP(GPR_INFO, elem, op);
GPR_TIMER_BEGIN("hs_start_transport_op", 0); GPR_TIMER_BEGIN("hs_start_transport_op", 0);
hs_mutate_op(elem, op); hs_mutate_op(exec_ctx, elem, op);
grpc_call_next_op(exec_ctx, elem, op); grpc_call_next_op(exec_ctx, elem, op);
GPR_TIMER_END("hs_start_transport_op", 0); GPR_TIMER_END("hs_start_transport_op", 0);
} }

@ -34,16 +34,14 @@
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/method_config.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/transport/service_config.h"
#define DEFAULT_MAX_SEND_MESSAGE_LENGTH -1 // Unlimited.
// The protobuf library will (by default) start warning at 100 megs.
#define DEFAULT_MAX_RECV_MESSAGE_LENGTH (4 * 1024 * 1024)
typedef struct message_size_limits { typedef struct message_size_limits {
int max_send_size; int max_send_size;
@ -56,30 +54,29 @@ static void* message_size_limits_copy(void* value) {
return new_value; return new_value;
} }
static int message_size_limits_cmp(void* value1, void* value2) {
const message_size_limits* v1 = value1;
const message_size_limits* v2 = value2;
if (v1->max_send_size > v2->max_send_size) return 1;
if (v1->max_send_size < v2->max_send_size) return -1;
if (v1->max_recv_size > v2->max_recv_size) return 1;
if (v1->max_recv_size < v2->max_recv_size) return -1;
return 0;
}
static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = { static const grpc_mdstr_hash_table_vtable message_size_limits_vtable = {
gpr_free, message_size_limits_copy, message_size_limits_cmp}; gpr_free, message_size_limits_copy};
static void* method_config_convert_value( static void* message_size_limits_create_from_json(const grpc_json* json) {
const grpc_method_config* method_config) { int max_request_message_bytes = -1;
int max_response_message_bytes = -1;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) continue;
if (strcmp(field->key, "maxRequestMessageBytes") == 0) {
if (max_request_message_bytes >= 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
max_request_message_bytes = gpr_parse_nonnegative_int(field->value);
if (max_request_message_bytes == -1) return NULL;
} else if (strcmp(field->key, "maxResponseMessageBytes") == 0) {
if (max_response_message_bytes >= 0) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
max_response_message_bytes = gpr_parse_nonnegative_int(field->value);
if (max_response_message_bytes == -1) return NULL;
}
}
message_size_limits* value = gpr_malloc(sizeof(message_size_limits)); message_size_limits* value = gpr_malloc(sizeof(message_size_limits));
const int32_t* max_request_message_bytes = value->max_send_size = max_request_message_bytes;
grpc_method_config_get_max_request_message_bytes(method_config); value->max_recv_size = max_response_message_bytes;
value->max_send_size =
max_request_message_bytes != NULL ? *max_request_message_bytes : -1;
const int32_t* max_response_message_bytes =
grpc_method_config_get_max_response_message_bytes(method_config);
value->max_recv_size =
max_response_message_bytes != NULL ? *max_response_message_bytes : -1;
return value; return value;
} }
@ -201,20 +198,20 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
GPR_ASSERT(!args->is_last); GPR_ASSERT(!args->is_last);
channel_data* chand = elem->channel_data; channel_data* chand = elem->channel_data;
memset(chand, 0, sizeof(*chand)); memset(chand, 0, sizeof(*chand));
chand->max_send_size = DEFAULT_MAX_SEND_MESSAGE_LENGTH; chand->max_send_size = GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH;
chand->max_recv_size = DEFAULT_MAX_RECV_MESSAGE_LENGTH; chand->max_recv_size = GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH;
for (size_t i = 0; i < args->channel_args->num_args; ++i) { for (size_t i = 0; i < args->channel_args->num_args; ++i) {
if (strcmp(args->channel_args->args[i].key, if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) { GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) {
const grpc_integer_options options = {DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, const grpc_integer_options options = {
INT_MAX}; GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, 0, INT_MAX};
chand->max_send_size = chand->max_send_size =
grpc_channel_arg_get_integer(&args->channel_args->args[i], options); grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
} }
if (strcmp(args->channel_args->args[i].key, if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) { GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
const grpc_integer_options options = {DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, const grpc_integer_options options = {
INT_MAX}; GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, 0, INT_MAX};
chand->max_recv_size = chand->max_recv_size =
grpc_channel_arg_get_integer(&args->channel_args->args[i], options); grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
} }
@ -223,10 +220,16 @@ static void init_channel_elem(grpc_exec_ctx* exec_ctx,
const grpc_arg* channel_arg = const grpc_arg* channel_arg =
grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG); grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
chand->method_limit_table = grpc_method_config_table_convert( grpc_service_config* service_config =
(grpc_method_config_table*)channel_arg->value.pointer.p, grpc_service_config_create(channel_arg->value.string);
method_config_convert_value, &message_size_limits_vtable); if (service_config != NULL) {
chand->method_limit_table =
grpc_service_config_create_method_config_table(
service_config, message_size_limits_create_from_json,
&message_size_limits_vtable);
grpc_service_config_destroy(service_config);
}
} }
} }

@ -72,6 +72,11 @@ static int grpc_polling_trace = 0; /* Disabled by default */
static int grpc_wakeup_signal = -1; static int grpc_wakeup_signal = -1;
static bool is_grpc_wakeup_signal_initialized = false; static bool is_grpc_wakeup_signal_initialized = false;
/* TODO: sreek: Right now, this wakes up all pollers. In future we should make
* sure to wake up one polling thread (which can wake up other threads if
* needed) */
static grpc_wakeup_fd global_wakeup_fd;
/* Implements the function defined in grpc_posix.h. This function might be /* Implements the function defined in grpc_posix.h. This function might be
* called before even calling grpc_init() to set either a different signal to * called before even calling grpc_init() to set either a different signal to
* use. If signum == -1, then the use of signals is disabled */ * use. If signum == -1, then the use of signals is disabled */
@ -437,9 +442,8 @@ static void polling_island_add_wakeup_fd_locked(polling_island *pi,
gpr_asprintf(&err_msg, gpr_asprintf(&err_msg,
"epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with " "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with "
"error: %d (%s)", "error: %d (%s)",
pi->epoll_fd, pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(&global_wakeup_fd),
GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd), errno, errno, strerror(errno));
strerror(errno));
append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc);
gpr_free(err_msg); gpr_free(err_msg);
} }
@ -541,7 +545,7 @@ static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx,
goto done; goto done;
} }
polling_island_add_wakeup_fd_locked(pi, &grpc_global_wakeup_fd, error); polling_island_add_wakeup_fd_locked(pi, &global_wakeup_fd, error);
polling_island_add_wakeup_fd_locked(pi, &pi->workqueue_wakeup_fd, error); polling_island_add_wakeup_fd_locked(pi, &pi->workqueue_wakeup_fd, error);
if (initial_fd != NULL) { if (initial_fd != NULL) {
@ -843,11 +847,6 @@ static void polling_island_global_shutdown() {
* alarm 'epoch'). This wakeup_fd gives us something to alert on when such a * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a
* case occurs. */ * case occurs. */
/* TODO: sreek: Right now, this wakes up all pollers. In future we should make
* sure to wake up one polling thread (which can wake up other threads if
* needed) */
grpc_wakeup_fd grpc_global_wakeup_fd;
static grpc_fd *fd_freelist = NULL; static grpc_fd *fd_freelist = NULL;
static gpr_mu fd_freelist_mu; static gpr_mu fd_freelist_mu;
@ -1163,11 +1162,11 @@ static grpc_error *pollset_global_init(void) {
gpr_tls_init(&g_current_thread_pollset); gpr_tls_init(&g_current_thread_pollset);
gpr_tls_init(&g_current_thread_worker); gpr_tls_init(&g_current_thread_worker);
poller_kick_init(); poller_kick_init();
return grpc_wakeup_fd_init(&grpc_global_wakeup_fd); return grpc_wakeup_fd_init(&global_wakeup_fd);
} }
static void pollset_global_shutdown(void) { static void pollset_global_shutdown(void) {
grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd); grpc_wakeup_fd_destroy(&global_wakeup_fd);
gpr_tls_destroy(&g_current_thread_pollset); gpr_tls_destroy(&g_current_thread_pollset);
gpr_tls_destroy(&g_current_thread_worker); gpr_tls_destroy(&g_current_thread_worker);
} }
@ -1274,7 +1273,7 @@ static grpc_error *pollset_kick(grpc_pollset *p,
} }
static grpc_error *kick_poller(void) { static grpc_error *kick_poller(void) {
return grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
} }
static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) {
@ -1501,13 +1500,11 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx,
for (int i = 0; i < ep_rv; ++i) { for (int i = 0; i < ep_rv; ++i) {
void *data_ptr = ep_ev[i].data.ptr; void *data_ptr = ep_ev[i].data.ptr;
if (data_ptr == &grpc_global_wakeup_fd) { if (data_ptr == &global_wakeup_fd) {
append_error(error, append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd),
err_desc); err_desc);
} else if (data_ptr == &pi->workqueue_wakeup_fd) { } else if (data_ptr == &pi->workqueue_wakeup_fd) {
append_error(error, append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd),
grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd),
err_desc); err_desc);
maybe_do_workqueue_work(exec_ctx, pi); maybe_do_workqueue_work(exec_ctx, pi);
} else if (data_ptr == &polling_island_wakeup_fd) { } else if (data_ptr == &polling_island_wakeup_fd) {

@ -120,6 +120,8 @@ struct grpc_fd {
grpc_pollset *read_notifier_pollset; grpc_pollset *read_notifier_pollset;
}; };
static grpc_wakeup_fd global_wakeup_fd;
/* Begin polling on an fd. /* Begin polling on an fd.
Registers that the given pollset is interested in this fd - so that if read Registers that the given pollset is interested in this fd - so that if read
or writability interest changes, the pollset can be kicked to pick up that or writability interest changes, the pollset can be kicked to pick up that
@ -769,17 +771,17 @@ static grpc_error *pollset_kick(grpc_pollset *p,
static grpc_error *pollset_global_init(void) { static grpc_error *pollset_global_init(void) {
gpr_tls_init(&g_current_thread_poller); gpr_tls_init(&g_current_thread_poller);
gpr_tls_init(&g_current_thread_worker); gpr_tls_init(&g_current_thread_worker);
return grpc_wakeup_fd_init(&grpc_global_wakeup_fd); return grpc_wakeup_fd_init(&global_wakeup_fd);
} }
static void pollset_global_shutdown(void) { static void pollset_global_shutdown(void) {
grpc_wakeup_fd_destroy(&grpc_global_wakeup_fd); grpc_wakeup_fd_destroy(&global_wakeup_fd);
gpr_tls_destroy(&g_current_thread_poller); gpr_tls_destroy(&g_current_thread_poller);
gpr_tls_destroy(&g_current_thread_worker); gpr_tls_destroy(&g_current_thread_worker);
} }
static grpc_error *kick_poller(void) { static grpc_error *kick_poller(void) {
return grpc_wakeup_fd_wakeup(&grpc_global_wakeup_fd); return grpc_wakeup_fd_wakeup(&global_wakeup_fd);
} }
/* main interface */ /* main interface */
@ -947,7 +949,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
fd_count = 0; fd_count = 0;
pfd_count = 2; pfd_count = 2;
pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&grpc_global_wakeup_fd); pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&global_wakeup_fd);
pfds[0].events = POLLIN; pfds[0].events = POLLIN;
pfds[0].revents = 0; pfds[0].revents = 0;
pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker.wakeup_fd->fd); pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker.wakeup_fd->fd);
@ -1001,8 +1003,8 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
} }
} else { } else {
if (pfds[0].revents & POLLIN_CHECK) { if (pfds[0].revents & POLLIN_CHECK) {
work_combine_error( work_combine_error(&error,
&error, grpc_wakeup_fd_consume_wakeup(&grpc_global_wakeup_fd)); grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd));
} }
if (pfds[1].revents & POLLIN_CHECK) { if (pfds[1].revents & POLLIN_CHECK) {
work_combine_error( work_combine_error(
@ -1343,6 +1345,7 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
int res, idx; int res, idx;
gpr_cv *pollcv; gpr_cv *pollcv;
cv_node *cvn, *prev; cv_node *cvn, *prev;
int skip_poll = 0;
nfds_t nsockfds = 0; nfds_t nsockfds = 0;
gpr_thd_id t_id; gpr_thd_id t_id;
gpr_thd_options opt; gpr_thd_options opt;
@ -1358,17 +1361,17 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
cvn->cv = pollcv; cvn->cv = pollcv;
cvn->next = g_cvfds.cvfds[idx].cvs; cvn->next = g_cvfds.cvfds[idx].cvs;
g_cvfds.cvfds[idx].cvs = cvn; g_cvfds.cvfds[idx].cvs = cvn;
// We should return immediately if there are pending events, // Don't bother polling if a wakeup fd is ready
// but we still need to call poll() to check for socket events
if (g_cvfds.cvfds[idx].is_set) { if (g_cvfds.cvfds[idx].is_set) {
timeout = 0; skip_poll = 1;
} }
} else if (fds[i].fd >= 0) { } else if (fds[i].fd >= 0) {
nsockfds++; nsockfds++;
} }
} }
if (nsockfds > 0) { res = 0;
if (!skip_poll && nsockfds > 0) {
pargs = gpr_malloc(sizeof(struct poll_args)); pargs = gpr_malloc(sizeof(struct poll_args));
// Both the main thread and calling thread get a reference // Both the main thread and calling thread get a reference
gpr_ref_init(&pargs->refcount, 2); gpr_ref_init(&pargs->refcount, 2);
@ -1398,16 +1401,14 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
res = pargs->retval; res = pargs->retval;
errno = pargs->err; errno = pargs->err;
} else { } else {
res = 0;
errno = 0; errno = 0;
gpr_atm_no_barrier_store(&pargs->status, CANCELLED); gpr_atm_no_barrier_store(&pargs->status, CANCELLED);
} }
} else { } else if (!skip_poll) {
gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME); gpr_timespec deadline = gpr_now(GPR_CLOCK_REALTIME);
deadline = deadline =
gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN)); gpr_time_add(deadline, gpr_time_from_millis(timeout, GPR_TIMESPAN));
gpr_cv_wait(pollcv, &g_cvfds.mu, deadline); gpr_cv_wait(pollcv, &g_cvfds.mu, deadline);
res = 0;
} }
idx = 0; idx = 0;
@ -1431,7 +1432,7 @@ static int cvfd_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
fds[i].revents = POLLIN; fds[i].revents = POLLIN;
if (res >= 0) res++; if (res >= 0) res++;
} }
} else if (fds[i].fd >= 0 && } else if (!skip_poll && fds[i].fd >= 0 &&
gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) { gpr_atm_no_barrier_load(&pargs->status) == COMPLETED) {
fds[i].revents = pargs->fds[idx].revents; fds[i].revents = pargs->fds[idx].revents;
idx++; idx++;

@ -183,6 +183,5 @@ void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx,
/* override to allow tests to hook poll() usage */ /* override to allow tests to hook poll() usage */
typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int); typedef int (*grpc_poll_function_type)(struct pollfd *, nfds_t, int);
extern grpc_poll_function_type grpc_poll_function; extern grpc_poll_function_type grpc_poll_function;
extern grpc_wakeup_fd grpc_global_wakeup_fd;
#endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */ #endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */

@ -108,6 +108,7 @@ void grpc_iomgr_shutdown(void) {
NULL)) { NULL)) {
gpr_mu_unlock(&g_mu); gpr_mu_unlock(&g_mu);
grpc_exec_ctx_flush(&exec_ctx); grpc_exec_ctx_flush(&exec_ctx);
grpc_iomgr_platform_flush();
gpr_mu_lock(&g_mu); gpr_mu_lock(&g_mu);
continue; continue;
} }

@ -104,6 +104,9 @@ struct grpc_resource_user {
/* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer /* Reclaimers: index 0 is the benign reclaimer, 1 is the destructive reclaimer
*/ */
grpc_closure *reclaimers[2]; grpc_closure *reclaimers[2];
/* Reclaimers just posted: once we're in the combiner lock, we'll move them
to the array above */
grpc_closure *new_reclaimers[2];
/* Trampoline closures to finish reclamation and re-enter the quota combiner /* Trampoline closures to finish reclamation and re-enter the quota combiner
lock */ lock */
grpc_closure post_reclaimer_closure[2]; grpc_closure post_reclaimer_closure[2];
@ -418,9 +421,25 @@ static void ru_add_to_free_pool(grpc_exec_ctx *exec_ctx, void *ru,
rulist_add_tail(resource_user, GRPC_RULIST_NON_EMPTY_FREE_POOL); rulist_add_tail(resource_user, GRPC_RULIST_NON_EMPTY_FREE_POOL);
} }
static bool ru_post_reclaimer(grpc_exec_ctx *exec_ctx,
grpc_resource_user *resource_user,
bool destructive) {
grpc_closure *closure = resource_user->new_reclaimers[destructive];
GPR_ASSERT(closure != NULL);
resource_user->new_reclaimers[destructive] = NULL;
GPR_ASSERT(resource_user->reclaimers[destructive] == NULL);
if (gpr_atm_acq_load(&resource_user->shutdown) > 0) {
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CANCELLED, NULL);
return false;
}
resource_user->reclaimers[destructive] = closure;
return true;
}
static void ru_post_benign_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, static void ru_post_benign_reclaimer(grpc_exec_ctx *exec_ctx, void *ru,
grpc_error *error) { grpc_error *error) {
grpc_resource_user *resource_user = ru; grpc_resource_user *resource_user = ru;
if (!ru_post_reclaimer(exec_ctx, resource_user, false)) return;
if (!rulist_empty(resource_user->resource_quota, if (!rulist_empty(resource_user->resource_quota,
GRPC_RULIST_AWAITING_ALLOCATION) && GRPC_RULIST_AWAITING_ALLOCATION) &&
rulist_empty(resource_user->resource_quota, rulist_empty(resource_user->resource_quota,
@ -435,6 +454,7 @@ static void ru_post_benign_reclaimer(grpc_exec_ctx *exec_ctx, void *ru,
static void ru_post_destructive_reclaimer(grpc_exec_ctx *exec_ctx, void *ru, static void ru_post_destructive_reclaimer(grpc_exec_ctx *exec_ctx, void *ru,
grpc_error *error) { grpc_error *error) {
grpc_resource_user *resource_user = ru; grpc_resource_user *resource_user = ru;
if (!ru_post_reclaimer(exec_ctx, resource_user, true)) return;
if (!rulist_empty(resource_user->resource_quota, if (!rulist_empty(resource_user->resource_quota,
GRPC_RULIST_AWAITING_ALLOCATION) && GRPC_RULIST_AWAITING_ALLOCATION) &&
rulist_empty(resource_user->resource_quota, rulist_empty(resource_user->resource_quota,
@ -649,6 +669,8 @@ grpc_resource_user *grpc_resource_user_create(
resource_user->added_to_free_pool = false; resource_user->added_to_free_pool = false;
resource_user->reclaimers[0] = NULL; resource_user->reclaimers[0] = NULL;
resource_user->reclaimers[1] = NULL; resource_user->reclaimers[1] = NULL;
resource_user->new_reclaimers[0] = NULL;
resource_user->new_reclaimers[1] = NULL;
for (int i = 0; i < GRPC_RULIST_COUNT; i++) { for (int i = 0; i < GRPC_RULIST_COUNT; i++) {
resource_user->links[i].next = resource_user->links[i].prev = NULL; resource_user->links[i].next = resource_user->links[i].prev = NULL;
} }
@ -748,12 +770,8 @@ void grpc_resource_user_post_reclaimer(grpc_exec_ctx *exec_ctx,
grpc_resource_user *resource_user, grpc_resource_user *resource_user,
bool destructive, bool destructive,
grpc_closure *closure) { grpc_closure *closure) {
GPR_ASSERT(resource_user->reclaimers[destructive] == NULL); GPR_ASSERT(resource_user->new_reclaimers[destructive] == NULL);
if (gpr_atm_acq_load(&resource_user->shutdown) > 0) { resource_user->new_reclaimers[destructive] = closure;
grpc_exec_ctx_sched(exec_ctx, closure, GRPC_ERROR_CANCELLED, NULL);
return;
}
resource_user->reclaimers[destructive] = closure;
grpc_combiner_execute(exec_ctx, resource_user->resource_quota->combiner, grpc_combiner_execute(exec_ctx, resource_user->resource_quota->combiner,
&resource_user->post_reclaimer_closure[destructive], &resource_user->post_reclaimer_closure[destructive],
GRPC_ERROR_NONE, false); GRPC_ERROR_NONE, false);

@ -76,6 +76,14 @@ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
LPFN_DISCONNECTEX DisconnectEx; LPFN_DISCONNECTEX DisconnectEx;
DWORD ioctl_num_bytes; DWORD ioctl_num_bytes;
gpr_mu_lock(&winsocket->state_mu);
if (winsocket->shutdown_called) {
gpr_mu_unlock(&winsocket->state_mu);
return;
}
winsocket->shutdown_called = true;
gpr_mu_unlock(&winsocket->state_mu);
status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER, status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx), &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx),
&ioctl_num_bytes, NULL, NULL); &ioctl_num_bytes, NULL, NULL);

@ -87,6 +87,7 @@ typedef struct grpc_winsocket {
grpc_winsocket_callback_info read_info; grpc_winsocket_callback_info read_info;
gpr_mu state_mu; gpr_mu state_mu;
bool shutdown_called;
/* You can't add the same socket twice to the same IO Completion Port. /* You can't add the same socket twice to the same IO Completion Port.
This prevents that. */ This prevents that. */

@ -251,8 +251,11 @@ finish:
done = (--ac->refs == 0); done = (--ac->refs == 0);
gpr_mu_unlock(&ac->mu); gpr_mu_unlock(&ac->mu);
if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_NONE) {
error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION, char *error_descr;
"Failed to connect to remote host"); gpr_asprintf(&error_descr, "Failed to connect to remote host: %s",
grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION));
error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION, error_descr);
gpr_free(error_descr);
error = error =
grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str); grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, ac->addr_str);
} }

@ -107,18 +107,22 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) {
gpr_mu_lock(&ac->mu); gpr_mu_lock(&ac->mu);
if (error == GRPC_ERROR_NONE && socket != NULL) { if (error == GRPC_ERROR_NONE) {
DWORD transfered_bytes = 0; if (socket != NULL) {
DWORD flags; DWORD transfered_bytes = 0;
BOOL wsa_success = DWORD flags;
WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped, BOOL wsa_success =
&transfered_bytes, FALSE, &flags); WSAGetOverlappedResult(socket->socket, &socket->write_info.overlapped,
GPR_ASSERT(transfered_bytes == 0); &transfered_bytes, FALSE, &flags);
if (!wsa_success) { GPR_ASSERT(transfered_bytes == 0);
error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx"); if (!wsa_success) {
error = GRPC_WSA_ERROR(WSAGetLastError(), "ConnectEx");
} else {
*ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name);
socket = NULL;
}
} else { } else {
*ep = grpc_tcp_create(socket, ac->resource_quota, ac->addr_name); error = GRPC_ERROR_CREATE("socket is null");
socket = NULL;
} }
} }

@ -73,6 +73,7 @@ struct grpc_tcp_listener {
/* The cached AcceptEx for that port. */ /* The cached AcceptEx for that port. */
LPFN_ACCEPTEX AcceptEx; LPFN_ACCEPTEX AcceptEx;
int shutting_down; int shutting_down;
int outstanding_calls;
/* closure for socket notification of accept being ready */ /* closure for socket notification of accept being ready */
grpc_closure on_accept; grpc_closure on_accept;
/* linked list */ /* linked list */
@ -140,10 +141,9 @@ grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { static void destroy_server(grpc_exec_ctx *exec_ctx, void *arg,
if (s->shutdown_complete != NULL) { grpc_error *error) {
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL); grpc_tcp_server *s = arg;
}
/* Now that the accepts have been aborted, we can destroy the sockets. /* 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 The IOCP won't get notified on these, so we can flag them as already
@ -159,6 +159,16 @@ static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
gpr_free(s); gpr_free(s);
} }
static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx,
grpc_tcp_server *s) {
if (s->shutdown_complete != NULL) {
grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
}
grpc_exec_ctx_sched(exec_ctx, grpc_closure_create(destroy_server, s),
GRPC_ERROR_NONE, NULL);
}
grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
gpr_ref_non_zero(&s->refs); gpr_ref_non_zero(&s->refs);
return s; return s;
@ -180,17 +190,14 @@ static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
/* First, shutdown all fd's. This will queue abortion calls for all /* First, shutdown all fd's. This will queue abortion calls for all
of the pending accepts due to the normal operation mechanism. */ of the pending accepts due to the normal operation mechanism. */
if (s->active_ports == 0) { if (s->active_ports == 0) {
immediately_done = 1; finish_shutdown_locked(exec_ctx, s);
} } else {
for (sp = s->head; sp; sp = sp->next) { for (sp = s->head; sp; sp = sp->next) {
sp->shutting_down = 1; sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket); grpc_winsocket_shutdown(sp->socket);
}
} }
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);
if (immediately_done) {
finish_shutdown(exec_ctx, s);
}
} }
void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
@ -251,31 +258,30 @@ failure:
return error; return error;
} }
static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx, static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx,
grpc_tcp_listener *sp) { grpc_tcp_listener *sp) {
int notify = 0; int notify = 0;
sp->shutting_down = 0; sp->shutting_down = 0;
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0); GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports) { if (0 == --sp->server->active_ports) {
notify = 1; finish_shutdown_locked(exec_ctx, sp->server);
}
gpr_mu_unlock(&sp->server->mu);
if (notify) {
finish_shutdown(exec_ctx, sp->server);
} }
} }
/* In order to do an async accept, we need to create a socket first which /* 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. */ will be the one assigned to the new incoming connection. */
static grpc_error *start_accept(grpc_exec_ctx *exec_ctx, static grpc_error *start_accept_locked(grpc_exec_ctx *exec_ctx,
grpc_tcp_listener *port) { grpc_tcp_listener *port) {
SOCKET sock = INVALID_SOCKET; SOCKET sock = INVALID_SOCKET;
BOOL success; BOOL success;
DWORD addrlen = sizeof(struct sockaddr_in6) + 16; DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
DWORD bytes_received = 0; DWORD bytes_received = 0;
grpc_error *error = GRPC_ERROR_NONE; grpc_error *error = GRPC_ERROR_NONE;
if (port->shutting_down) {
return GRPC_ERROR_NONE;
}
sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0, sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
WSA_FLAG_OVERLAPPED); WSA_FLAG_OVERLAPPED);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
@ -305,20 +311,11 @@ static grpc_error *start_accept(grpc_exec_ctx *exec_ctx,
immediately process an accept that happened in the meantime. */ immediately process an accept that happened in the meantime. */
port->new_socket = sock; port->new_socket = sock;
grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept); grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
port->outstanding_calls++;
return error; return error;
failure: failure:
GPR_ASSERT(error != GRPC_ERROR_NONE); GPR_ASSERT(error != GRPC_ERROR_NONE);
if (port->shutting_down) {
/* We are abandoning the listener port, take that into account to prevent
occasional hangs on shutdown. The hang happens when sp->shutting_down
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(exec_ctx, port);
GRPC_ERROR_UNREF(error);
return GRPC_ERROR_NONE;
}
if (sock != INVALID_SOCKET) closesocket(sock); if (sock != INVALID_SOCKET) closesocket(sock);
return error; return error;
} }
@ -338,6 +335,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
BOOL wsa_success; BOOL wsa_success;
int err; int err;
gpr_mu_lock(&sp->server->mu);
peer_name.len = sizeof(struct sockaddr_storage); peer_name.len = sizeof(struct sockaddr_storage);
/* The general mechanism for shutting down is to queue abortion calls. While /* The general mechanism for shutting down is to queue abortion calls. While
@ -347,6 +346,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
const char *msg = grpc_error_string(error); const char *msg = grpc_error_string(error);
gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg); gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg);
grpc_error_free_string(msg); grpc_error_free_string(msg);
gpr_mu_unlock(&sp->server->mu);
return; return;
} }
@ -356,17 +356,12 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
&transfered_bytes, FALSE, &flags); &transfered_bytes, FALSE, &flags);
if (!wsa_success) { if (!wsa_success) {
if (sp->shutting_down) { 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(exec_ctx, sp);
return;
} else {
char *utf8_message = gpr_format_message(WSAGetLastError()); char *utf8_message = gpr_format_message(WSAGetLastError());
gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message); gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
gpr_free(utf8_message); gpr_free(utf8_message);
closesocket(sock);
} }
closesocket(sock);
} else { } else {
if (!sp->shutting_down) { if (!sp->shutting_down) {
peer_name_string = NULL; peer_name_string = NULL;
@ -408,7 +403,12 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
the former socked we created has now either been destroy or assigned 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 to the new connection. We need to create a new one for the next
connection. */ connection. */
GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp))); GPR_ASSERT(
GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp)));
if (0 == --sp->outstanding_calls) {
decrement_active_ports_and_notify_locked(exec_ctx, sp);
}
gpr_mu_unlock(&sp->server->mu);
} }
static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock, static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
@ -456,6 +456,7 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
sp->server = s; sp->server = s;
sp->socket = grpc_winsocket_create(sock, "listener"); sp->socket = grpc_winsocket_create(sock, "listener");
sp->shutting_down = 0; sp->shutting_down = 0;
sp->outstanding_calls = 0;
sp->AcceptEx = AcceptEx; sp->AcceptEx = AcceptEx;
sp->new_socket = INVALID_SOCKET; sp->new_socket = INVALID_SOCKET;
sp->port = port; sp->port = port;
@ -553,7 +554,8 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
s->on_accept_cb = on_accept_cb; s->on_accept_cb = on_accept_cb;
s->on_accept_cb_arg = on_accept_cb_arg; s->on_accept_cb_arg = on_accept_cb_arg;
for (sp = s->head; sp; sp = sp->next) { for (sp = s->head; sp; sp = sp->next) {
GPR_ASSERT(GRPC_LOG_IF_ERROR("start_accept", start_accept(exec_ctx, sp))); GPR_ASSERT(
GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp)));
s->active_ports++; s->active_ports++;
} }
gpr_mu_unlock(&s->mu); gpr_mu_unlock(&s->mu);

@ -423,7 +423,7 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket,
tcp->base.vtable = &vtable; tcp->base.vtable = &vtable;
tcp->socket = socket; tcp->socket = socket;
gpr_mu_init(&tcp->mu); gpr_mu_init(&tcp->mu);
gpr_ref_init(&tcp->refcount, 2); gpr_ref_init(&tcp->refcount, 1);
grpc_closure_init(&tcp->on_read, on_read, tcp); grpc_closure_init(&tcp->on_read, on_read, tcp);
grpc_closure_init(&tcp->on_write, on_write, tcp); grpc_closure_init(&tcp->on_write, on_write, tcp);
tcp->peer_string = gpr_strdup(peer_string); tcp->peer_string = gpr_strdup(peer_string);

@ -37,15 +37,15 @@
#include "src/core/lib/json/json.h" #include "src/core/lib/json/json.h"
grpc_json *grpc_json_create(grpc_json_type type) { grpc_json* grpc_json_create(grpc_json_type type) {
grpc_json *json = gpr_malloc(sizeof(*json)); grpc_json* json = gpr_malloc(sizeof(*json));
memset(json, 0, sizeof(*json)); memset(json, 0, sizeof(*json));
json->type = type; json->type = type;
return json; return json;
} }
void grpc_json_destroy(grpc_json *json) { void grpc_json_destroy(grpc_json* json) {
while (json->child) { while (json->child) {
grpc_json_destroy(json->child); grpc_json_destroy(json->child);
} }

@ -42,14 +42,14 @@
* are not owned by it. * are not owned by it.
*/ */
typedef struct grpc_json { typedef struct grpc_json {
struct grpc_json *next; struct grpc_json* next;
struct grpc_json *prev; struct grpc_json* prev;
struct grpc_json *child; struct grpc_json* child;
struct grpc_json *parent; struct grpc_json* parent;
grpc_json_type type; grpc_json_type type;
const char *key; const char* key;
const char *value; const char* value;
} grpc_json; } grpc_json;
/* The next two functions are going to parse the input string, and /* The next two functions are going to parse the input string, and
@ -65,8 +65,8 @@ typedef struct grpc_json {
* *
* Delete the allocated tree afterward using grpc_json_destroy(). * Delete the allocated tree afterward using grpc_json_destroy().
*/ */
grpc_json *grpc_json_parse_string_with_len(char *input, size_t size); grpc_json* grpc_json_parse_string_with_len(char* input, size_t size);
grpc_json *grpc_json_parse_string(char *input); grpc_json* grpc_json_parse_string(char* input);
/* This function will create a new string using gpr_realloc, and will /* This function will create a new string using gpr_realloc, and will
* deserialize the grpc_json tree into it. It'll be zero-terminated, * deserialize the grpc_json tree into it. It'll be zero-terminated,
@ -76,13 +76,13 @@ grpc_json *grpc_json_parse_string(char *input);
* If indent is 0, then newlines will be suppressed as well, and the * If indent is 0, then newlines will be suppressed as well, and the
* output will be condensed at its maximum. * output will be condensed at its maximum.
*/ */
char *grpc_json_dump_to_string(grpc_json *json, int indent); char* grpc_json_dump_to_string(grpc_json* json, int indent);
/* Use these to create or delete a grpc_json object. /* Use these to create or delete a grpc_json object.
* Deletion is recursive. We will not attempt to free any of the strings * Deletion is recursive. We will not attempt to free any of the strings
* in any of the objects of that tree. * in any of the objects of that tree.
*/ */
grpc_json *grpc_json_create(grpc_json_type type); grpc_json* grpc_json_create(grpc_json_type type);
void grpc_json_destroy(grpc_json *json); void grpc_json_destroy(grpc_json* json);
#endif /* GRPC_CORE_LIB_JSON_JSON_H */ #endif /* GRPC_CORE_LIB_JSON_JSON_H */

@ -348,3 +348,11 @@ int grpc_slice_str_cmp(grpc_slice a, const char *b) {
if (d != 0) return d; if (d != 0) return d;
return memcmp(GRPC_SLICE_START_PTR(a), b, b_length); return memcmp(GRPC_SLICE_START_PTR(a), b, b_length);
} }
int grpc_slice_is_equivalent(grpc_slice a, grpc_slice b) {
if (a.refcount == NULL || b.refcount == NULL) {
return grpc_slice_cmp(a, b) == 0;
}
return a.data.refcounted.length == b.data.refcounted.length &&
a.data.refcounted.bytes == b.data.refcounted.bytes;
}

@ -34,7 +34,9 @@
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -189,6 +191,13 @@ int int64_ttoa(int64_t value, char *string) {
return i; return i;
} }
int gpr_parse_nonnegative_int(const char *value) {
char *end;
long result = strtol(value, &end, 0);
if (*end != '\0' || result < 0 || result > INT_MAX) return -1;
return (int)result;
}
char *gpr_leftpad(const char *str, char flag, size_t length) { char *gpr_leftpad(const char *str, char flag, size_t length) {
const size_t str_length = strlen(str); const size_t str_length = strlen(str);
const size_t out_length = str_length > length ? str_length : length; const size_t out_length = str_length > length ? str_length : length;

@ -77,6 +77,9 @@ NOTE: This function ensures sufficient bit width even on Win x64,
where long is 32bit is size.*/ where long is 32bit is size.*/
int int64_ttoa(int64_t value, char *output); int int64_ttoa(int64_t value, char *output);
// Parses a non-negative number from a value string. Returns -1 on error.
int gpr_parse_nonnegative_int(const char *value);
/* Reverse a run of bytes */ /* Reverse a run of bytes */
void gpr_reverse_bytes(char *str, int len); void gpr_reverse_bytes(char *str, int len);

@ -40,6 +40,7 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -52,7 +53,7 @@
struct gpr_subprocess { struct gpr_subprocess {
int pid; int pid;
int joined; bool joined;
}; };
const char *gpr_subprocess_binary_extension() { return ""; } const char *gpr_subprocess_binary_extension() { return ""; }
@ -97,9 +98,11 @@ retry:
if (errno == EINTR) { if (errno == EINTR) {
goto retry; goto retry;
} }
gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno)); gpr_log(GPR_ERROR, "waitpid failed for pid %d: %s", p->pid,
strerror(errno));
return -1; return -1;
} }
p->joined = true;
return status; return status;
} }

@ -637,9 +637,6 @@ static int prepare_application_metadata(grpc_call *call, int count,
if (call->send_extra_metadata_count == 0) { if (call->send_extra_metadata_count == 0) {
prepend_extra_metadata = 0; prepend_extra_metadata = 0;
} else { } else {
for (i = 0; i < call->send_extra_metadata_count; i++) {
GRPC_MDELEM_REF(call->send_extra_metadata[i].md);
}
for (i = 1; i < call->send_extra_metadata_count; i++) { for (i = 1; i < call->send_extra_metadata_count; i++) {
call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1]; call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
} }
@ -685,6 +682,7 @@ static int prepare_application_metadata(grpc_call *call, int count,
&call->send_extra_metadata[call->send_extra_metadata_count - 1]; &call->send_extra_metadata[call->send_extra_metadata_count - 1];
batch->list.head->prev = NULL; batch->list.head->prev = NULL;
batch->list.tail->next = NULL; batch->list.tail->next = NULL;
call->send_extra_metadata_count = 0;
break; break;
case 3: { case 3: {
/* prepend AND md */ /* prepend AND md */
@ -700,6 +698,7 @@ static int prepare_application_metadata(grpc_call *call, int count,
batch->list.tail = linked_from_md(last_md); batch->list.tail = linked_from_md(last_md);
batch->list.head->prev = NULL; batch->list.head->prev = NULL;
batch->list.tail->next = NULL; batch->list.tail->next = NULL;
call->send_extra_metadata_count = 0;
break; break;
} }
default: default:

@ -195,6 +195,7 @@ struct grpc_server {
grpc_completion_queue **cqs; grpc_completion_queue **cqs;
grpc_pollset **pollsets; grpc_pollset **pollsets;
size_t cq_count; size_t cq_count;
size_t pollset_count;
bool started; bool started;
/* The two following mutexes control access to server-state /* The two following mutexes control access to server-state
@ -1085,7 +1086,7 @@ void grpc_server_start(grpc_server *server) {
GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server)); GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server));
server->started = true; server->started = true;
size_t pollset_count = 0; server->pollset_count = 0;
server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count);
server->request_freelist_per_cq = server->request_freelist_per_cq =
gpr_malloc(sizeof(*server->request_freelist_per_cq) * server->cq_count); gpr_malloc(sizeof(*server->request_freelist_per_cq) * server->cq_count);
@ -1093,7 +1094,8 @@ void grpc_server_start(grpc_server *server) {
gpr_malloc(sizeof(*server->requested_calls_per_cq) * server->cq_count); gpr_malloc(sizeof(*server->requested_calls_per_cq) * server->cq_count);
for (i = 0; i < server->cq_count; i++) { for (i = 0; i < server->cq_count; i++) {
if (!grpc_cq_is_non_listening_server_cq(server->cqs[i])) { if (!grpc_cq_is_non_listening_server_cq(server->cqs[i])) {
server->pollsets[pollset_count++] = grpc_cq_pollset(server->cqs[i]); server->pollsets[server->pollset_count++] =
grpc_cq_pollset(server->cqs[i]);
} }
server->request_freelist_per_cq[i] = server->request_freelist_per_cq[i] =
gpr_stack_lockfree_create((size_t)server->max_requested_calls_per_cq); gpr_stack_lockfree_create((size_t)server->max_requested_calls_per_cq);
@ -1112,7 +1114,8 @@ void grpc_server_start(grpc_server *server) {
} }
for (l = server->listeners; l; l = l->next) { for (l = server->listeners; l; l = l->next) {
l->start(&exec_ctx, server, l->arg, server->pollsets, pollset_count); l->start(&exec_ctx, server, l->arg, server->pollsets,
server->pollset_count);
} }
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
@ -1120,7 +1123,7 @@ void grpc_server_start(grpc_server *server) {
void grpc_server_get_pollsets(grpc_server *server, grpc_pollset ***pollsets, void grpc_server_get_pollsets(grpc_server *server, grpc_pollset ***pollsets,
size_t *pollset_count) { size_t *pollset_count) {
*pollset_count = server->cq_count; *pollset_count = server->pollset_count;
*pollsets = server->pollsets; *pollsets = server->pollsets;
} }

@ -100,7 +100,12 @@ grpc_connectivity_state grpc_connectivity_state_check(
return tracker->current_state; return tracker->current_state;
} }
int grpc_connectivity_state_notify_on_state_change( bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker *connectivity_state) {
return connectivity_state->watchers != NULL;
}
bool grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state *current, grpc_closure *notify) { grpc_connectivity_state *current, grpc_closure *notify) {
if (grpc_connectivity_state_trace) { if (grpc_connectivity_state_trace) {
@ -119,7 +124,7 @@ int grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL); grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
tracker->watchers = w->next; tracker->watchers = w->next;
gpr_free(w); gpr_free(w);
return 0; return false;
} }
while (w != NULL) { while (w != NULL) {
grpc_connectivity_state_watcher *rm_candidate = w->next; grpc_connectivity_state_watcher *rm_candidate = w->next;
@ -127,11 +132,11 @@ int grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL); grpc_exec_ctx_sched(exec_ctx, notify, GRPC_ERROR_CANCELLED, NULL);
w->next = w->next->next; w->next = w->next->next;
gpr_free(rm_candidate); gpr_free(rm_candidate);
return 0; return false;
} }
w = w->next; w = w->next;
} }
return 0; return false;
} else { } else {
if (tracker->current_state != *current) { if (tracker->current_state != *current) {
*current = tracker->current_state; *current = tracker->current_state;

@ -75,13 +75,16 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx,
grpc_error *associated_error, grpc_error *associated_error,
const char *reason); const char *reason);
bool grpc_connectivity_state_has_watchers(
grpc_connectivity_state_tracker *tracker);
grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state grpc_connectivity_state_check(
grpc_connectivity_state_tracker *tracker, grpc_error **current_error); grpc_connectivity_state_tracker *tracker, grpc_error **current_error);
/** Return 1 if the channel should start connecting, 0 otherwise. /** Return 1 if the channel should start connecting, 0 otherwise.
If current==NULL cancel notify if it is already queued (success==0 in that If current==NULL cancel notify if it is already queued (success==0 in that
case) */ case) */
int grpc_connectivity_state_notify_on_state_change( bool grpc_connectivity_state_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker, grpc_exec_ctx *exec_ctx, grpc_connectivity_state_tracker *tracker,
grpc_connectivity_state *current, grpc_closure *notify); grpc_connectivity_state *current, grpc_closure *notify);

@ -41,7 +41,6 @@
struct grpc_mdstr_hash_table { struct grpc_mdstr_hash_table {
gpr_refcount refs; gpr_refcount refs;
size_t num_entries;
size_t size; size_t size;
grpc_mdstr_hash_table_entry* entries; grpc_mdstr_hash_table_entry* entries;
}; };
@ -77,7 +76,6 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table)); grpc_mdstr_hash_table* table = gpr_malloc(sizeof(*table));
memset(table, 0, sizeof(*table)); memset(table, 0, sizeof(*table));
gpr_ref_init(&table->refs, 1); gpr_ref_init(&table->refs, 1);
table->num_entries = num_entries;
// Quadratic probing gets best performance when the table is no more // Quadratic probing gets best performance when the table is no more
// than half full. // than half full.
table->size = num_entries * 2; table->size = num_entries * 2;
@ -96,7 +94,7 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table) {
return table; return table;
} }
int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) { void grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) {
if (table != NULL && gpr_unref(&table->refs)) { if (table != NULL && gpr_unref(&table->refs)) {
for (size_t i = 0; i < table->size; ++i) { for (size_t i = 0; i < table->size; ++i) {
grpc_mdstr_hash_table_entry* entry = &table->entries[i]; grpc_mdstr_hash_table_entry* entry = &table->entries[i];
@ -107,13 +105,7 @@ int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table) {
} }
gpr_free(table->entries); gpr_free(table->entries);
gpr_free(table); gpr_free(table);
return 1;
} }
return 0;
}
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table) {
return table->num_entries;
} }
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
@ -123,35 +115,3 @@ void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
if (idx == table->size) return NULL; // Not found. if (idx == table->size) return NULL; // Not found.
return table->entries[idx].value; return table->entries[idx].value;
} }
int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
const grpc_mdstr_hash_table* table2) {
// Compare by num_entries.
if (table1->num_entries < table2->num_entries) return -1;
if (table1->num_entries > table2->num_entries) return 1;
for (size_t i = 0; i < table1->num_entries; ++i) {
grpc_mdstr_hash_table_entry* e1 = &table1->entries[i];
grpc_mdstr_hash_table_entry* e2 = &table2->entries[i];
// Compare keys by hash value.
if (e1->key->hash < e2->key->hash) return -1;
if (e1->key->hash > e2->key->hash) return 1;
// Compare by vtable (pointer equality).
if (e1->vtable < e2->vtable) return -1;
if (e1->vtable > e2->vtable) return 1;
// Compare values via vtable.
const int value_result = e1->vtable->compare_value(e1->value, e2->value);
if (value_result != 0) return value_result;
}
return 0;
}
void grpc_mdstr_hash_table_iterate(
const grpc_mdstr_hash_table* table,
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
void* user_data) {
for (size_t i = 0; i < table->size; ++i) {
if (table->entries[i].key != NULL) {
func(&table->entries[i], user_data);
}
}
}

@ -51,7 +51,6 @@ typedef struct grpc_mdstr_hash_table grpc_mdstr_hash_table;
typedef struct grpc_mdstr_hash_table_vtable { typedef struct grpc_mdstr_hash_table_vtable {
void (*destroy_value)(void* value); void (*destroy_value)(void* value);
void* (*copy_value)(void* value); void* (*copy_value)(void* value);
int (*compare_value)(void* value1, void* value2);
} grpc_mdstr_hash_table_vtable; } grpc_mdstr_hash_table_vtable;
typedef struct grpc_mdstr_hash_table_entry { typedef struct grpc_mdstr_hash_table_entry {
@ -67,26 +66,11 @@ grpc_mdstr_hash_table* grpc_mdstr_hash_table_create(
size_t num_entries, grpc_mdstr_hash_table_entry* entries); size_t num_entries, grpc_mdstr_hash_table_entry* entries);
grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table); grpc_mdstr_hash_table* grpc_mdstr_hash_table_ref(grpc_mdstr_hash_table* table);
/** Returns 1 when \a table is destroyed. */ void grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table);
int grpc_mdstr_hash_table_unref(grpc_mdstr_hash_table* table);
/** Returns the number of entries in \a table. */
size_t grpc_mdstr_hash_table_num_entries(const grpc_mdstr_hash_table* table);
/** Returns the value from \a table associated with \a key. /** Returns the value from \a table associated with \a key.
Returns NULL if \a key is not found. */ Returns NULL if \a key is not found. */
void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table, void* grpc_mdstr_hash_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* key); const grpc_mdstr* key);
/** Compares two hash tables.
The sort order is stable but undefined. */
int grpc_mdstr_hash_table_cmp(const grpc_mdstr_hash_table* table1,
const grpc_mdstr_hash_table* table2);
/** Iterates over the entries in \a table, calling \a func for each entry. */
void grpc_mdstr_hash_table_iterate(
const grpc_mdstr_hash_table* table,
void (*func)(const grpc_mdstr_hash_table_entry* entry, void* user_data),
void* user_data);
#endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */ #endif /* GRPC_CORE_LIB_TRANSPORT_MDSTR_HASH_TABLE_H */

@ -1,340 +0,0 @@
//
// 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/lib/transport/method_config.h"
#include <string.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/lib/transport/mdstr_hash_table.h"
#include "src/core/lib/transport/metadata.h"
//
// grpc_method_config
//
// bool vtable
static void* bool_copy(void* valuep) {
bool value = *(bool*)valuep;
bool* new_value = gpr_malloc(sizeof(bool));
*new_value = value;
return new_value;
}
static int bool_cmp(void* v1, void* v2) {
bool b1 = *(bool*)v1;
bool b2 = *(bool*)v2;
if (!b1 && b2) return -1;
if (b1 && !b2) return 1;
return 0;
}
static grpc_mdstr_hash_table_vtable bool_vtable = {gpr_free, bool_copy,
bool_cmp};
// timespec vtable
static void* timespec_copy(void* valuep) {
gpr_timespec value = *(gpr_timespec*)valuep;
gpr_timespec* new_value = gpr_malloc(sizeof(gpr_timespec));
*new_value = value;
return new_value;
}
static int timespec_cmp(void* v1, void* v2) {
return gpr_time_cmp(*(gpr_timespec*)v1, *(gpr_timespec*)v2);
}
static grpc_mdstr_hash_table_vtable timespec_vtable = {gpr_free, timespec_copy,
timespec_cmp};
// int32 vtable
static void* int32_copy(void* valuep) {
int32_t value = *(int32_t*)valuep;
int32_t* new_value = gpr_malloc(sizeof(int32_t));
*new_value = value;
return new_value;
}
static int int32_cmp(void* v1, void* v2) {
int32_t i1 = *(int32_t*)v1;
int32_t i2 = *(int32_t*)v2;
if (i1 < i2) return -1;
if (i1 > i2) return 1;
return 0;
}
static grpc_mdstr_hash_table_vtable int32_vtable = {gpr_free, int32_copy,
int32_cmp};
// Hash table keys.
#define GRPC_METHOD_CONFIG_WAIT_FOR_READY "grpc.wait_for_ready" // bool
#define GRPC_METHOD_CONFIG_TIMEOUT "grpc.timeout" // gpr_timespec
#define GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES \
"grpc.max_request_message_bytes" // int32
#define GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES \
"grpc.max_response_message_bytes" // int32
struct grpc_method_config {
grpc_mdstr_hash_table* table;
grpc_mdstr* wait_for_ready_key;
grpc_mdstr* timeout_key;
grpc_mdstr* max_request_message_bytes_key;
grpc_mdstr* max_response_message_bytes_key;
};
grpc_method_config* grpc_method_config_create(
bool* wait_for_ready, gpr_timespec* timeout,
int32_t* max_request_message_bytes, int32_t* max_response_message_bytes) {
grpc_method_config* method_config = gpr_malloc(sizeof(grpc_method_config));
memset(method_config, 0, sizeof(grpc_method_config));
method_config->wait_for_ready_key =
grpc_mdstr_from_string(GRPC_METHOD_CONFIG_WAIT_FOR_READY);
method_config->timeout_key =
grpc_mdstr_from_string(GRPC_METHOD_CONFIG_TIMEOUT);
method_config->max_request_message_bytes_key =
grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_REQUEST_MESSAGE_BYTES);
method_config->max_response_message_bytes_key =
grpc_mdstr_from_string(GRPC_METHOD_CONFIG_MAX_RESPONSE_MESSAGE_BYTES);
grpc_mdstr_hash_table_entry entries[4];
size_t num_entries = 0;
if (wait_for_ready != NULL) {
entries[num_entries].key = method_config->wait_for_ready_key;
entries[num_entries].value = wait_for_ready;
entries[num_entries].vtable = &bool_vtable;
++num_entries;
}
if (timeout != NULL) {
entries[num_entries].key = method_config->timeout_key;
entries[num_entries].value = timeout;
entries[num_entries].vtable = &timespec_vtable;
++num_entries;
}
if (max_request_message_bytes != NULL) {
entries[num_entries].key = method_config->max_request_message_bytes_key;
entries[num_entries].value = max_request_message_bytes;
entries[num_entries].vtable = &int32_vtable;
++num_entries;
}
if (max_response_message_bytes != NULL) {
entries[num_entries].key = method_config->max_response_message_bytes_key;
entries[num_entries].value = max_response_message_bytes;
entries[num_entries].vtable = &int32_vtable;
++num_entries;
}
method_config->table = grpc_mdstr_hash_table_create(num_entries, entries);
return method_config;
}
grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config) {
grpc_mdstr_hash_table_ref(method_config->table);
return method_config;
}
void grpc_method_config_unref(grpc_method_config* method_config) {
if (grpc_mdstr_hash_table_unref(method_config->table)) {
GRPC_MDSTR_UNREF(method_config->wait_for_ready_key);
GRPC_MDSTR_UNREF(method_config->timeout_key);
GRPC_MDSTR_UNREF(method_config->max_request_message_bytes_key);
GRPC_MDSTR_UNREF(method_config->max_response_message_bytes_key);
gpr_free(method_config);
}
}
int grpc_method_config_cmp(const grpc_method_config* method_config1,
const grpc_method_config* method_config2) {
return grpc_mdstr_hash_table_cmp(method_config1->table,
method_config2->table);
}
const bool* grpc_method_config_get_wait_for_ready(
const grpc_method_config* method_config) {
return grpc_mdstr_hash_table_get(method_config->table,
method_config->wait_for_ready_key);
}
const gpr_timespec* grpc_method_config_get_timeout(
const grpc_method_config* method_config) {
return grpc_mdstr_hash_table_get(method_config->table,
method_config->timeout_key);
}
const int32_t* grpc_method_config_get_max_request_message_bytes(
const grpc_method_config* method_config) {
return grpc_mdstr_hash_table_get(
method_config->table, method_config->max_request_message_bytes_key);
}
const int32_t* grpc_method_config_get_max_response_message_bytes(
const grpc_method_config* method_config) {
return grpc_mdstr_hash_table_get(
method_config->table, method_config->max_response_message_bytes_key);
}
//
// grpc_method_config_table
//
static void method_config_unref(void* valuep) {
grpc_method_config_unref(valuep);
}
static void* method_config_ref(void* valuep) {
return grpc_method_config_ref(valuep);
}
static int method_config_cmp(void* valuep1, void* valuep2) {
return grpc_method_config_cmp(valuep1, valuep2);
}
static const grpc_mdstr_hash_table_vtable method_config_table_vtable = {
method_config_unref, method_config_ref, method_config_cmp};
grpc_method_config_table* grpc_method_config_table_create(
size_t num_entries, grpc_method_config_table_entry* entries) {
grpc_mdstr_hash_table_entry* hash_table_entries =
gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) * num_entries);
for (size_t i = 0; i < num_entries; ++i) {
hash_table_entries[i].key = entries[i].method_name;
hash_table_entries[i].value = entries[i].method_config;
hash_table_entries[i].vtable = &method_config_table_vtable;
}
grpc_method_config_table* method_config_table =
grpc_mdstr_hash_table_create(num_entries, hash_table_entries);
gpr_free(hash_table_entries);
return method_config_table;
}
grpc_method_config_table* grpc_method_config_table_ref(
grpc_method_config_table* table) {
return grpc_mdstr_hash_table_ref(table);
}
void grpc_method_config_table_unref(grpc_method_config_table* table) {
grpc_mdstr_hash_table_unref(table);
}
int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
const grpc_method_config_table* table2) {
return grpc_mdstr_hash_table_cmp(table1, table2);
}
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* path) {
void* value = grpc_mdstr_hash_table_get(table, path);
// If we didn't find a match for the path, try looking for a wildcard
// entry (i.e., change "/service/method" to "/service/*").
if (value == NULL) {
const char* path_str = grpc_mdstr_as_c_string(path);
const char* sep = strrchr(path_str, '/') + 1;
const size_t len = (size_t)(sep - path_str);
char* buf = gpr_malloc(len + 2); // '*' and NUL
memcpy(buf, path_str, len);
buf[len] = '*';
buf[len + 1] = '\0';
grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
gpr_free(buf);
value = grpc_mdstr_hash_table_get(table, wildcard_path);
GRPC_MDSTR_UNREF(wildcard_path);
}
return value;
}
static void* copy_arg(void* p) { return grpc_method_config_table_ref(p); }
static void destroy_arg(void* p) { grpc_method_config_table_unref(p); }
static int cmp_arg(void* p1, void* p2) {
return grpc_method_config_table_cmp(p1, p2);
}
static grpc_arg_pointer_vtable arg_vtable = {copy_arg, destroy_arg, cmp_arg};
grpc_arg grpc_method_config_table_create_channel_arg(
grpc_method_config_table* table) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_SERVICE_CONFIG;
arg.value.pointer.p = table;
arg.value.pointer.vtable = &arg_vtable;
return arg;
}
// State used by convert_entry() below.
typedef struct conversion_state {
void* (*convert_value)(const grpc_method_config* method_config);
const grpc_mdstr_hash_table_vtable* vtable;
size_t num_entries;
grpc_mdstr_hash_table_entry* entries;
} conversion_state;
// A function to be passed to grpc_mdstr_hash_table_iterate() to create
// a copy of the entries.
static void convert_entry(const grpc_mdstr_hash_table_entry* entry,
void* user_data) {
conversion_state* state = user_data;
state->entries[state->num_entries].key = GRPC_MDSTR_REF(entry->key);
state->entries[state->num_entries].value = state->convert_value(entry->value);
state->entries[state->num_entries].vtable = state->vtable;
++state->num_entries;
}
grpc_mdstr_hash_table* grpc_method_config_table_convert(
const grpc_method_config_table* table,
void* (*convert_value)(const grpc_method_config* method_config),
const grpc_mdstr_hash_table_vtable* vtable) {
// Create an array of the entries in the table with converted values.
conversion_state state;
state.convert_value = convert_value;
state.vtable = vtable;
state.num_entries = 0;
state.entries = gpr_malloc(sizeof(grpc_mdstr_hash_table_entry) *
grpc_mdstr_hash_table_num_entries(table));
grpc_mdstr_hash_table_iterate(table, convert_entry, &state);
// Create a new table based on the array we just constructed.
grpc_mdstr_hash_table* new_table =
grpc_mdstr_hash_table_create(state.num_entries, state.entries);
// Clean up the array.
for (size_t i = 0; i < state.num_entries; ++i) {
GRPC_MDSTR_UNREF(state.entries[i].key);
vtable->destroy_value(state.entries[i].value);
}
gpr_free(state.entries);
// Return the new table.
return new_table;
}

@ -1,136 +0,0 @@
//
// Copyright 2016, 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_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
#define GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H
#include <stdbool.h>
#include <grpc/impl/codegen/gpr_types.h>
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/transport/mdstr_hash_table.h"
#include "src/core/lib/transport/metadata.h"
/// Per-method configuration.
typedef struct grpc_method_config grpc_method_config;
/// Creates a grpc_method_config with the specified parameters.
/// Any parameter may be NULL to indicate that the value is unset.
///
/// \a wait_for_ready indicates whether the client should wait until the
/// request deadline for the channel to become ready, even if there is a
/// temporary failure before the deadline while attempting to connect.
///
/// \a timeout indicates the timeout for calls.
///
/// \a max_request_message_bytes and \a max_response_message_bytes
/// indicate the maximum sizes of the request (checked when sending) and
/// response (checked when receiving) messages.
grpc_method_config* grpc_method_config_create(
bool* wait_for_ready, gpr_timespec* timeout,
int32_t* max_request_message_bytes, int32_t* max_response_message_bytes);
grpc_method_config* grpc_method_config_ref(grpc_method_config* method_config);
void grpc_method_config_unref(grpc_method_config* method_config);
/// Compares two grpc_method_configs.
/// The sort order is stable but undefined.
int grpc_method_config_cmp(const grpc_method_config* method_config1,
const grpc_method_config* method_config2);
/// These methods return NULL if the requested field is unset.
/// The caller does NOT take ownership of the result.
const bool* grpc_method_config_get_wait_for_ready(
const grpc_method_config* method_config);
const gpr_timespec* grpc_method_config_get_timeout(
const grpc_method_config* method_config);
const int32_t* grpc_method_config_get_max_request_message_bytes(
const grpc_method_config* method_config);
const int32_t* grpc_method_config_get_max_response_message_bytes(
const grpc_method_config* method_config);
/// A table of method configs.
typedef grpc_mdstr_hash_table grpc_method_config_table;
typedef struct grpc_method_config_table_entry {
/// The name is of one of the following forms:
/// service/method -- specifies exact service and method name
/// service/* -- matches all methods for the specified service
grpc_mdstr* method_name;
grpc_method_config* method_config;
} grpc_method_config_table_entry;
/// Takes new references to all keys and values in \a entries.
grpc_method_config_table* grpc_method_config_table_create(
size_t num_entries, grpc_method_config_table_entry* entries);
grpc_method_config_table* grpc_method_config_table_ref(
grpc_method_config_table* table);
void grpc_method_config_table_unref(grpc_method_config_table* table);
/// Compares two grpc_method_config_tables.
/// The sort order is stable but undefined.
int grpc_method_config_table_cmp(const grpc_method_config_table* table1,
const grpc_method_config_table* table2);
/// Gets the method config for the specified \a path, which should be of
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
///
/// Note: This returns a void* instead of a grpc_method_config* so that
/// it can also be used for tables constructed via
/// grpc_method_config_table_convert().
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* path);
/// Returns a channel arg containing \a table.
grpc_arg grpc_method_config_table_create_channel_arg(
grpc_method_config_table* table);
/// Generates a new table from \a table whose values are converted to a
/// new form via the \a convert_value function. The new table will use
/// \a vtable for its values.
///
/// This is generally used to convert the table's value type from
/// grpc_method_config to a simple struct containing only the parameters
/// relevant to a particular filter, thus avoiding the need for a hash
/// table lookup on the fast path. In that scenario, \a convert_value
/// will return a new instance of the struct containing the values from
/// the grpc_method_config, and \a vtable provides the methods for
/// operating on the struct type.
grpc_mdstr_hash_table* grpc_method_config_table_convert(
const grpc_method_config_table* table,
void* (*convert_value)(const grpc_method_config* method_config),
const grpc_mdstr_hash_table_vtable* vtable);
#endif /* GRPC_CORE_LIB_TRANSPORT_METHOD_CONFIG_H */

@ -0,0 +1,249 @@
//
// 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/lib/transport/service_config.h"
#include <string.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/json/json.h"
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/mdstr_hash_table.h"
// The main purpose of the code here is to parse the service config in
// JSON form, which will look like this:
//
// {
// "loadBalancingPolicy": "string", // optional
// "methodConfig": [ // array of one or more method_config objects
// {
// "name": [ // array of one or more name objects
// {
// "service": "string", // required
// "method": "string", // optional
// }
// ],
// // remaining fields are optional.
// // see https://developers.google.com/protocol-buffers/docs/proto3#json
// // for format details.
// "waitForReady": bool,
// "timeout": "duration_string",
// "maxRequestMessageBytes": "int64_string",
// "maxResponseMessageBytes": "int64_string",
// }
// ]
// }
struct grpc_service_config {
char* json_string; // Underlying storage for json_tree.
grpc_json* json_tree;
};
grpc_service_config* grpc_service_config_create(const char* json_string) {
grpc_service_config* service_config = gpr_malloc(sizeof(*service_config));
service_config->json_string = gpr_strdup(json_string);
service_config->json_tree =
grpc_json_parse_string(service_config->json_string);
if (service_config->json_tree == NULL) {
gpr_log(GPR_INFO, "failed to parse JSON for service config");
gpr_free(service_config->json_string);
gpr_free(service_config);
return NULL;
}
return service_config;
}
void grpc_service_config_destroy(grpc_service_config* service_config) {
grpc_json_destroy(service_config->json_tree);
gpr_free(service_config->json_string);
gpr_free(service_config);
}
const char* grpc_service_config_get_lb_policy_name(
const grpc_service_config* service_config) {
const grpc_json* json = service_config->json_tree;
if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL;
const char* lb_policy_name = NULL;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) return NULL;
if (strcmp(field->key, "loadBalancingPolicy") == 0) {
if (lb_policy_name != NULL) return NULL; // Duplicate.
if (field->type != GRPC_JSON_STRING) return NULL;
lb_policy_name = field->value;
}
}
return lb_policy_name;
}
// Returns the number of names specified in the method config \a json.
static size_t count_names_in_method_config_json(grpc_json* json) {
size_t num_names = 0;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key != NULL && strcmp(field->key, "name") == 0) ++num_names;
}
return num_names;
}
// Returns a path string for the JSON name object specified by \a json.
// Returns NULL on error. Caller takes ownership of result.
static char* parse_json_method_name(grpc_json* json) {
if (json->type != GRPC_JSON_OBJECT) return NULL;
const char* service_name = NULL;
const char* method_name = NULL;
for (grpc_json* child = json->child; child != NULL; child = child->next) {
if (child->key == NULL) return NULL;
if (child->type != GRPC_JSON_STRING) return NULL;
if (strcmp(child->key, "service") == 0) {
if (service_name != NULL) return NULL; // Duplicate.
if (child->value == NULL) return NULL;
service_name = child->value;
} else if (strcmp(child->key, "method") == 0) {
if (method_name != NULL) return NULL; // Duplicate.
if (child->value == NULL) return NULL;
method_name = child->value;
}
}
if (service_name == NULL) return NULL; // Required field.
char* path;
gpr_asprintf(&path, "/%s/%s", service_name,
method_name == NULL ? "*" : method_name);
return path;
}
// Parses the method config from \a json. Adds an entry to \a entries for
// each name found, incrementing \a idx for each entry added.
// Returns false on error.
static bool parse_json_method_config(
grpc_json* json, void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable,
grpc_mdstr_hash_table_entry* entries, size_t* idx) {
// Construct value.
void* method_config = create_value(json);
if (method_config == NULL) return false;
// Construct list of paths.
bool success = false;
gpr_strvec paths;
gpr_strvec_init(&paths);
for (grpc_json* child = json->child; child != NULL; child = child->next) {
if (child->key == NULL) continue;
if (strcmp(child->key, "name") == 0) {
if (child->type != GRPC_JSON_ARRAY) goto done;
for (grpc_json* name = child->child; name != NULL; name = name->next) {
char* path = parse_json_method_name(name);
gpr_strvec_add(&paths, path);
}
}
}
if (paths.count == 0) goto done; // No names specified.
// Add entry for each path.
for (size_t i = 0; i < paths.count; ++i) {
entries[*idx].key = grpc_mdstr_from_string(paths.strs[i]);
entries[*idx].value = vtable->copy_value(method_config);
entries[*idx].vtable = vtable;
++*idx;
}
success = true;
done:
vtable->destroy_value(method_config);
gpr_strvec_destroy(&paths);
return success;
}
grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
const grpc_service_config* service_config,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable) {
const grpc_json* json = service_config->json_tree;
// Traverse parsed JSON tree.
if (json->type != GRPC_JSON_OBJECT || json->key != NULL) return NULL;
size_t num_entries = 0;
grpc_mdstr_hash_table_entry* entries = NULL;
for (grpc_json* field = json->child; field != NULL; field = field->next) {
if (field->key == NULL) return NULL;
if (strcmp(field->key, "methodConfig") == 0) {
if (entries != NULL) return NULL; // Duplicate.
if (field->type != GRPC_JSON_ARRAY) return NULL;
// Find number of entries.
for (grpc_json* method = field->child; method != NULL;
method = method->next) {
num_entries += count_names_in_method_config_json(method);
}
// Populate method config table entries.
entries = gpr_malloc(num_entries * sizeof(grpc_mdstr_hash_table_entry));
size_t idx = 0;
for (grpc_json* method = field->child; method != NULL;
method = method->next) {
if (!parse_json_method_config(method, create_value, vtable, entries,
&idx)) {
return NULL;
}
}
GPR_ASSERT(idx == num_entries);
}
}
// Instantiate method config table.
grpc_mdstr_hash_table* method_config_table = NULL;
if (entries != NULL) {
method_config_table = grpc_mdstr_hash_table_create(num_entries, entries);
// Clean up.
for (size_t i = 0; i < num_entries; ++i) {
GRPC_MDSTR_UNREF(entries[i].key);
vtable->destroy_value(entries[i].value);
}
gpr_free(entries);
}
return method_config_table;
}
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* path) {
void* value = grpc_mdstr_hash_table_get(table, path);
// If we didn't find a match for the path, try looking for a wildcard
// entry (i.e., change "/service/method" to "/service/*").
if (value == NULL) {
const char* path_str = grpc_mdstr_as_c_string(path);
const char* sep = strrchr(path_str, '/') + 1;
const size_t len = (size_t)(sep - path_str);
char* buf = gpr_malloc(len + 2); // '*' and NUL
memcpy(buf, path_str, len);
buf[len] = '*';
buf[len + 1] = '\0';
grpc_mdstr* wildcard_path = grpc_mdstr_from_string(buf);
gpr_free(buf);
value = grpc_mdstr_hash_table_get(table, wildcard_path);
GRPC_MDSTR_UNREF(wildcard_path);
}
return value;
}

@ -0,0 +1,70 @@
//
// Copyright 2016, 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_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H
#define GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/json/json.h"
#include "src/core/lib/transport/mdstr_hash_table.h"
typedef struct grpc_service_config grpc_service_config;
grpc_service_config* grpc_service_config_create(const char* json_string);
void grpc_service_config_destroy(grpc_service_config* service_config);
/// Gets the LB policy name from \a service_config.
/// Returns NULL if no LB policy name was specified.
/// Caller does NOT take ownership.
const char* grpc_service_config_get_lb_policy_name(
const grpc_service_config* service_config);
/// Creates a method config table based on the data in \a json.
/// The table's keys are request paths. The table's value type is
/// returned by \a create_value(), based on data parsed from the JSON tree.
/// \a vtable provides methods used to manage the values.
/// Returns NULL on error.
grpc_mdstr_hash_table* grpc_service_config_create_method_config_table(
const grpc_service_config* service_config,
void* (*create_value)(const grpc_json* method_config_json),
const grpc_mdstr_hash_table_vtable* vtable);
/// A helper function for looking up values in the table returned by
/// \a grpc_service_config_create_method_config_table().
/// Gets the method config for the specified \a path, which should be of
/// the form "/service/method".
/// Returns NULL if the method has no config.
/// Caller does NOT own a reference to the result.
void* grpc_method_config_table_get(const grpc_mdstr_hash_table* table,
const grpc_mdstr* path);
#endif /* GRPC_CORE_LIB_TRANSPORT_SERVICE_CONFIG_H */

@ -48,6 +48,7 @@
#include <grpc++/support/time.h> #include <grpc++/support/time.h>
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/slice.h> #include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
@ -61,6 +62,35 @@ Channel::Channel(const grpc::string& host, grpc_channel* channel)
Channel::~Channel() { grpc_channel_destroy(c_channel_); } Channel::~Channel() { grpc_channel_destroy(c_channel_); }
namespace {
grpc::string GetChannelInfoField(grpc_channel* channel,
grpc_channel_info* channel_info,
char*** channel_info_field) {
char* value = NULL;
memset(channel_info, 0, sizeof(*channel_info));
*channel_info_field = &value;
grpc_channel_get_info(channel, channel_info);
if (value == NULL) return "";
grpc::string result = value;
gpr_free(value);
return result;
}
} // namespace
grpc::string Channel::GetLoadBalancingPolicyName() const {
grpc_channel_info channel_info;
return GetChannelInfoField(c_channel_, &channel_info,
&channel_info.lb_policy_name);
}
grpc::string Channel::GetServiceConfigJSON() const {
grpc_channel_info channel_info;
return GetChannelInfoField(c_channel_, &channel_info,
&channel_info.service_config_json);
}
Call Channel::CreateCall(const RpcMethod& method, ClientContext* context, Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
CompletionQueue* cq) { CompletionQueue* cq) {
const bool kRegistered = method.channel_tag() && context->authority().empty(); const bool kRegistered = method.channel_tag() && context->authority().empty();

@ -143,6 +143,11 @@ void ChannelArguments::SetLoadBalancingPolicyName(
SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name); SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name);
} }
void ChannelArguments::SetServiceConfigJSON(
const grpc::string& service_config_json) {
SetString(GRPC_ARG_SERVICE_CONFIG, service_config_json);
}
void ChannelArguments::SetInt(const grpc::string& key, int value) { void ChannelArguments::SetInt(const grpc::string& key, int value) {
grpc_arg arg; grpc_arg arg;
arg.type = GRPC_ARG_INTEGER; arg.type = GRPC_ARG_INTEGER;

@ -15,7 +15,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -39,15 +39,15 @@
<Reference Include="nunit.framework"> <Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath> <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="nunitlite"> <Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath> <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs"> <Compile Include="..\Grpc.Core\Version.cs">

@ -115,7 +115,8 @@ namespace Grpc.Core.Tests
var otherAssemblies = new[] { var otherAssemblies = new[] {
"Grpc.Examples.Tests", "Grpc.Examples.Tests",
"Grpc.HealthCheck.Tests", "Grpc.HealthCheck.Tests",
"Grpc.IntegrationTesting" "Grpc.IntegrationTesting",
"Grpc.Reflection.Tests",
}; };
foreach (var assemblyName in otherAssemblies) foreach (var assemblyName in otherAssemblies)
{ {

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" /> <package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" /> <package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" />
<package id="NUnit.ConsoleRunner" version="3.2.0" /> <package id="NUnit.ConsoleRunner" version="3.2.0" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" />
<package id="OpenCover" version="4.6.519" /> <package id="OpenCover" version="4.6.519" />
<package id="ReportGenerator" version="2.4.4.0" /> <package id="ReportGenerator" version="2.4.4.0" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> </packages>

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -26,7 +25,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -40,7 +40,7 @@
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Interactive.Async"> <Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath> <HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

@ -15,7 +15,7 @@
<copyright>Copyright 2015, Google Inc.</copyright> <copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2</tags> <tags>gRPC RPC Protocol HTTP/2</tags>
<dependencies> <dependencies>
<dependency id="System.Interactive.Async" version="3.0.0" /> <dependency id="System.Interactive.Async" version="3.1.1" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> </packages>

@ -27,11 +27,10 @@
"embed": [ "../../../etc/roots.pem" ], "embed": [ "../../../etc/roots.pem" ],
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true "xmlDoc": true
}, },
"dependencies": { "dependencies": {
"System.Interactive.Async": "3.0.0" "System.Interactive.Async": "3.1.1"
}, },
"frameworks": { "frameworks": {
"net45": { }, "net45": { },

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.25123.0 VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Core", "Grpc.Core\Grpc.Core.xproj", "{DC9908B6-F291-4FC8-A46D-2EA2551790EC}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Core", "Grpc.Core\Grpc.Core.xproj", "{DC9908B6-F291-4FC8-A46D-2EA2551790EC}"
EndProject EndProject
@ -31,6 +31,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.Ser
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.xproj", "{0EBC910B-8867-4D3E-8686-91F34183D839}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.xproj", "{0EBC910B-8867-4D3E-8686-91F34183D839}"
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.xproj", "{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.xproj", "{FE90181D-A4B3-4A5C-8490-F07561E18E3B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -93,6 +97,14 @@ Global
{0EBC910B-8867-4D3E-8686-91F34183D839}.Debug|Any CPU.Build.0 = Debug|Any CPU {0EBC910B-8867-4D3E-8686-91F34183D839}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.ActiveCfg = Release|Any CPU {0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.Build.0 = Release|Any CPU {0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.Build.0 = Release|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.Build.0 = Release|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -26,7 +25,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -26,7 +25,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -39,15 +39,15 @@
<Reference Include="nunit.framework"> <Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath> <HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="nunitlite"> <Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath> <HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
</Reference> </Reference>
<Reference Include="Google.Protobuf"> <Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs"> <Compile Include="..\Grpc.Core\Version.cs">

@ -3,5 +3,5 @@
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" /> <package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" /> <package id="NUnitLite" version="3.2.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> </packages>

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -26,7 +25,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -42,13 +42,12 @@
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data.Linq" /> <Reference Include="System.Data.Linq" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf"> <Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs"> <Compile Include="..\Grpc.Core\Version.cs">

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto // source: math/math.proto
#pragma warning disable 1591, 0612, 3021 #pragma warning disable 1591, 0612, 3021
#region Designer generated code #region Designer generated code
@ -9,11 +9,11 @@ using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic; using scg = global::System.Collections.Generic;
namespace Math { namespace Math {
/// <summary>Holder for reflection information generated from math.proto</summary> /// <summary>Holder for reflection information generated from math/math.proto</summary>
public static partial class MathReflection { public static partial class MathReflection {
#region Descriptor #region Descriptor
/// <summary>File descriptor for math.proto</summary> /// <summary>File descriptor for math/math.proto</summary>
public static pbr::FileDescriptor Descriptor { public static pbr::FileDescriptor Descriptor {
get { return descriptor; } get { return descriptor; }
} }
@ -22,15 +22,15 @@ namespace Math {
static MathReflection() { static MathReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String( byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat( string.Concat(
"CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB", "Cg9tYXRoL21hdGgucHJvdG8SBG1hdGgiLAoHRGl2QXJncxIQCghkaXZpZGVu",
"KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB", "ZBgBIAEoAxIPCgdkaXZpc29yGAIgASgDIi8KCERpdlJlcGx5EhAKCHF1b3Rp",
"IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB", "ZW50GAEgASgDEhEKCXJlbWFpbmRlchgCIAEoAyIYCgdGaWJBcmdzEg0KBWxp",
"IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50", "bWl0GAEgASgDIhIKA051bRILCgNudW0YASABKAMiGQoIRmliUmVwbHkSDQoF",
"GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu", "Y291bnQYASABKAMypAEKBE1hdGgSJgoDRGl2Eg0ubWF0aC5EaXZBcmdzGg4u",
"RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E", "bWF0aC5EaXZSZXBseSIAEi4KB0Rpdk1hbnkSDS5tYXRoLkRpdkFyZ3MaDi5t",
"aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51", "YXRoLkRpdlJlcGx5IgAoATABEiMKA0ZpYhINLm1hdGguRmliQXJncxoJLm1h",
"bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAFiBnByb3Rv", "dGguTnVtIgAwARIfCgNTdW0SCS5tYXRoLk51bRoJLm1hdGguTnVtIgAoAWIG",
"Mw==")); "cHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { }, new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: math.proto // source: math/math.proto
// Original file comments: // Original file comments:
// Copyright 2015, Google Inc. // Copyright 2015, Google Inc.
// All rights reserved. // All rights reserved.
@ -38,7 +38,7 @@ using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
namespace Math { namespace Math {
public static class Math public static partial class Math
{ {
static readonly string __ServiceName = "math.Math"; static readonly string __ServiceName = "math.Math";
@ -82,7 +82,7 @@ namespace Math {
} }
/// <summary>Base class for server-side implementations of Math</summary> /// <summary>Base class for server-side implementations of Math</summary>
public abstract class MathBase public abstract partial class MathBase
{ {
/// <summary> /// <summary>
/// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
@ -126,7 +126,7 @@ namespace Math {
} }
/// <summary>Client for Math</summary> /// <summary>Client for Math</summary>
public class MathClient : ClientBase<MathClient> public partial class MathClient : ClientBase<MathClient>
{ {
/// <summary>Creates a new client for Math</summary> /// <summary>Creates a new client for Math</summary>
/// <param name="channel">The channel to use to make remote calls.</param> /// <param name="channel">The channel to use to make remote calls.</param>

@ -2,5 +2,5 @@
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" /> <package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> </packages>

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -26,7 +25,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -40,10 +40,6 @@
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\System.Interactive.Async.3.0.0\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@ -52,6 +48,9 @@
<Reference Include="Google.Protobuf"> <Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath> <HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs"> <Compile Include="..\Grpc.Core\Version.cs">

@ -16,7 +16,7 @@
<dependencies> <dependencies>
<dependency id="Google.Protobuf" version="$ProtobufVersion$" /> <dependency id="Google.Protobuf" version="$ProtobufVersion$" />
<dependency id="Grpc.Core" version="$version$" /> <dependency id="Grpc.Core" version="$version$" />
<dependency id="System.Interactive.Async" version="3.0.0" /> <dependency id="System.Interactive.Async" version="3.1.1" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: health.proto // source: grpc/health/v1/health.proto
#pragma warning disable 1591, 0612, 3021 #pragma warning disable 1591, 0612, 3021
#region Designer generated code #region Designer generated code
@ -9,11 +9,11 @@ using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic; using scg = global::System.Collections.Generic;
namespace Grpc.Health.V1 { namespace Grpc.Health.V1 {
/// <summary>Holder for reflection information generated from health.proto</summary> /// <summary>Holder for reflection information generated from grpc/health/v1/health.proto</summary>
public static partial class HealthReflection { public static partial class HealthReflection {
#region Descriptor #region Descriptor
/// <summary>File descriptor for health.proto</summary> /// <summary>File descriptor for grpc/health/v1/health.proto</summary>
public static pbr::FileDescriptor Descriptor { public static pbr::FileDescriptor Descriptor {
get { return descriptor; } get { return descriptor; }
} }
@ -22,14 +22,14 @@ namespace Grpc.Health.V1 {
static HealthReflection() { static HealthReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String( byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat( string.Concat(
"CgxoZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYxIiUKEkhlYWx0aENoZWNr", "ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx",
"UmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNIZWFsdGhDaGVja1Jlc3Bv", "IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNI",
"bnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVhbHRoLnYxLkhlYWx0aENo", "ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh",
"ZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1TZXJ2aW5nU3RhdHVzEgsK", "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1T",
"B1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9UX1NFUlZJTkcQAjJaCgZI", "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U",
"ZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jl", "X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52",
"cXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhDaGVja1Jlc3BvbnNlQhGq", "MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD",
"Ag5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z")); "aGVja1Jlc3BvbnNlQhGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { }, new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
// source: health.proto // source: grpc/health/v1/health.proto
// Original file comments: // Original file comments:
// Copyright 2015, Google Inc. // Copyright 2015, Google Inc.
// All rights reserved. // All rights reserved.
@ -38,7 +38,7 @@ using System.Threading.Tasks;
using Grpc.Core; using Grpc.Core;
namespace Grpc.Health.V1 { namespace Grpc.Health.V1 {
public static class Health public static partial class Health
{ {
static readonly string __ServiceName = "grpc.health.v1.Health"; static readonly string __ServiceName = "grpc.health.v1.Health";
@ -59,7 +59,7 @@ namespace Grpc.Health.V1 {
} }
/// <summary>Base class for server-side implementations of Health</summary> /// <summary>Base class for server-side implementations of Health</summary>
public abstract class HealthBase public abstract partial class HealthBase
{ {
public virtual global::System.Threading.Tasks.Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context) public virtual global::System.Threading.Tasks.Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context)
{ {
@ -69,7 +69,7 @@ namespace Grpc.Health.V1 {
} }
/// <summary>Client for Health</summary> /// <summary>Client for Health</summary>
public class HealthClient : ClientBase<HealthClient> public partial class HealthClient : ClientBase<HealthClient>
{ {
/// <summary>Creates a new client for Health</summary> /// <summary>Creates a new client for Health</summary>
/// <param name="channel">The channel to use to make remote calls.</param> /// <param name="channel">The channel to use to make remote calls.</param>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" /> <package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" /> <package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages> </packages>

@ -15,7 +15,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -29,7 +28,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -29,7 +28,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -29,7 +28,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -7,7 +7,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]
@ -29,7 +28,6 @@
"buildOptions": { "buildOptions": {
"define": [ "SIGNED" ], "define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk", "keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true, "xmlDoc": true,
"compile": { "compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ] "includeFiles": [ "../Grpc.Core/Version.cs" ]

@ -45,44 +45,48 @@ namespace Grpc.Testing {
"dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr", "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
"Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy", "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
"Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS", "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
"LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSKWAgoMU2VydmVyQ29u", "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSK0AgoMU2VydmVyQ29u",
"ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl", "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
"clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n", "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
"LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy", "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
"X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk", "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
"X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK", "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
"CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJImgK", "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJEhwK",
"ClNlcnZlckFyZ3MSKwoFc2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2Vy", "E3Jlc291cmNlX3F1b3RhX3NpemUY6QcgASgFImgKClNlcnZlckFyZ3MSKwoF",
"dmVyQ29uZmlnSAASIgoEbWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJr", "c2V0dXAYASABKAsyGi5ncnBjLnRlc3RpbmcuU2VydmVyQ29uZmlnSAASIgoE",
"SABCCQoHYXJndHlwZSJVCgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsy", "bWFyaxgCIAEoCzISLmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSJV",
"GS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVj", "CgxTZXJ2ZXJTdGF0dXMSKAoFc3RhdHMYASABKAsyGS5ncnBjLnRlc3Rpbmcu",
"b3JlcxgDIAEoBSINCgtDb3JlUmVxdWVzdCIdCgxDb3JlUmVzcG9uc2USDQoF", "U2VydmVyU3RhdHMSDAoEcG9ydBgCIAEoBRINCgVjb3JlcxgDIAEoBSINCgtD",
"Y29yZXMYASABKAUiBgoEVm9pZCL9AQoIU2NlbmFyaW8SDAoEbmFtZRgBIAEo", "b3JlUmVxdWVzdCIdCgxDb3JlUmVzcG9uc2USDQoFY29yZXMYASABKAUiBgoE",
"CRIxCg1jbGllbnRfY29uZmlnGAIgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVu", "Vm9pZCL9AQoIU2NlbmFyaW8SDAoEbmFtZRgBIAEoCRIxCg1jbGllbnRfY29u",
"dENvbmZpZxITCgtudW1fY2xpZW50cxgDIAEoBRIxCg1zZXJ2ZXJfY29uZmln", "ZmlnGAIgASgLMhouZ3JwYy50ZXN0aW5nLkNsaWVudENvbmZpZxITCgtudW1f",
"GAQgASgLMhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZxITCgtudW1fc2Vy", "Y2xpZW50cxgDIAEoBRIxCg1zZXJ2ZXJfY29uZmlnGAQgASgLMhouZ3JwYy50",
"dmVycxgFIAEoBRIWCg53YXJtdXBfc2Vjb25kcxgGIAEoBRIZChFiZW5jaG1h", "ZXN0aW5nLlNlcnZlckNvbmZpZxITCgtudW1fc2VydmVycxgFIAEoBRIWCg53",
"cmtfc2Vjb25kcxgHIAEoBRIgChhzcGF3bl9sb2NhbF93b3JrZXJfY291bnQY", "YXJtdXBfc2Vjb25kcxgGIAEoBRIZChFiZW5jaG1hcmtfc2Vjb25kcxgHIAEo",
"CCABKAUiNgoJU2NlbmFyaW9zEikKCXNjZW5hcmlvcxgBIAMoCzIWLmdycGMu", "BRIgChhzcGF3bl9sb2NhbF93b3JrZXJfY291bnQYCCABKAUiNgoJU2NlbmFy",
"dGVzdGluZy5TY2VuYXJpbyKSAgoVU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EgsK", "aW9zEikKCXNjZW5hcmlvcxgBIAMoCzIWLmdycGMudGVzdGluZy5TY2VuYXJp",
"A3FwcxgBIAEoARIbChNxcHNfcGVyX3NlcnZlcl9jb3JlGAIgASgBEhoKEnNl", "byL4AgoVU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EgsKA3FwcxgBIAEoARIbChNx",
"cnZlcl9zeXN0ZW1fdGltZRgDIAEoARIYChBzZXJ2ZXJfdXNlcl90aW1lGAQg", "cHNfcGVyX3NlcnZlcl9jb3JlGAIgASgBEhoKEnNlcnZlcl9zeXN0ZW1fdGlt",
"ASgBEhoKEmNsaWVudF9zeXN0ZW1fdGltZRgFIAEoARIYChBjbGllbnRfdXNl", "ZRgDIAEoARIYChBzZXJ2ZXJfdXNlcl90aW1lGAQgASgBEhoKEmNsaWVudF9z",
"cl90aW1lGAYgASgBEhIKCmxhdGVuY3lfNTAYByABKAESEgoKbGF0ZW5jeV85", "eXN0ZW1fdGltZRgFIAEoARIYChBjbGllbnRfdXNlcl90aW1lGAYgASgBEhIK",
"MBgIIAEoARISCgpsYXRlbmN5Xzk1GAkgASgBEhIKCmxhdGVuY3lfOTkYCiAB", "CmxhdGVuY3lfNTAYByABKAESEgoKbGF0ZW5jeV85MBgIIAEoARISCgpsYXRl",
"KAESEwoLbGF0ZW5jeV85OTkYCyABKAEiyAIKDlNjZW5hcmlvUmVzdWx0EigK", "bmN5Xzk1GAkgASgBEhIKCmxhdGVuY3lfOTkYCiABKAESEwoLbGF0ZW5jeV85",
"CHNjZW5hcmlvGAEgASgLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxh", "OTkYCyABKAESGAoQc2VydmVyX2NwdV91c2FnZRgMIAEoARImCh5zdWNjZXNz",
"dGVuY2llcxgCIAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8K", "ZnVsX3JlcXVlc3RzX3Blcl9zZWNvbmQYDSABKAESIgoaZmFpbGVkX3JlcXVl",
"DGNsaWVudF9zdGF0cxgDIAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0", "c3RzX3Blcl9zZWNvbmQYDiABKAEigwMKDlNjZW5hcmlvUmVzdWx0EigKCHNj",
"cxIvCgxzZXJ2ZXJfc3RhdHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVy", "ZW5hcmlvGAEgASgLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxhdGVu",
"U3RhdHMSFAoMc2VydmVyX2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsy", "Y2llcxgCIAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8KDGNs",
"Iy5ncnBjLnRlc3RpbmcuU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EhYKDmNsaWVu", "aWVudF9zdGF0cxgDIAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cxIv",
"dF9zdWNjZXNzGAcgAygIEhYKDnNlcnZlcl9zdWNjZXNzGAggAygIKkEKCkNs", "CgxzZXJ2ZXJfc3RhdHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3Rh",
"aWVudFR5cGUSDwoLU1lOQ19DTElFTlQQABIQCgxBU1lOQ19DTElFTlQQARIQ", "dHMSFAoMc2VydmVyX2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsyIy5n",
"CgxPVEhFUl9DTElFTlQQAipbCgpTZXJ2ZXJUeXBlEg8KC1NZTkNfU0VSVkVS", "cnBjLnRlc3RpbmcuU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EhYKDmNsaWVudF9z",
"EAASEAoMQVNZTkNfU0VSVkVSEAESGAoUQVNZTkNfR0VORVJJQ19TRVJWRVIQ", "dWNjZXNzGAcgAygIEhYKDnNlcnZlcl9zdWNjZXNzGAggAygIEjkKD3JlcXVl",
"AhIQCgxPVEhFUl9TRVJWRVIQAyojCgdScGNUeXBlEgkKBVVOQVJZEAASDQoJ", "c3RfcmVzdWx0cxgJIAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0",
"U1RSRUFNSU5HEAFiBnByb3RvMw==")); "Q291bnQqQQoKQ2xpZW50VHlwZRIPCgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5D",
"X0NMSUVOVBABEhAKDE9USEVSX0NMSUVOVBACKlsKClNlcnZlclR5cGUSDwoL",
"U1lOQ19TRVJWRVIQABIQCgxBU1lOQ19TRVJWRVIQARIYChRBU1lOQ19HRU5F",
"UklDX1NFUlZFUhACEhAKDE9USEVSX1NFUlZFUhADKiMKB1JwY1R5cGUSCQoF",
"VU5BUlkQABINCglTVFJFQU1JTkcQAWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, }, new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
@ -94,7 +98,7 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerConfig), global::Grpc.Testing.ServerConfig.Parser, new[]{ "ServerType", "SecurityParams", "Port", "AsyncServerThreads", "CoreLimit", "PayloadConfig", "CoreList", "OtherServerApi", "ResourceQuotaSize" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerArgs), global::Grpc.Testing.ServerArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ServerStatus), global::Grpc.Testing.ServerStatus.Parser, new[]{ "Stats", "Port", "Cores" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.CoreRequest), global::Grpc.Testing.CoreRequest.Parser, null, null, null, null),
@ -102,8 +106,8 @@ namespace Grpc.Testing {
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Void), global::Grpc.Testing.Void.Parser, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenario), global::Grpc.Testing.Scenario.Parser, new[]{ "Name", "ClientConfig", "NumClients", "ServerConfig", "NumServers", "WarmupSeconds", "BenchmarkSeconds", "SpawnLocalWorkerCount" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Scenarios), global::Grpc.Testing.Scenarios.Parser, new[]{ "Scenarios_" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResultSummary), global::Grpc.Testing.ScenarioResultSummary.Parser, new[]{ "Qps", "QpsPerServerCore", "ServerSystemTime", "ServerUserTime", "ClientSystemTime", "ClientUserTime", "Latency50", "Latency90", "Latency95", "Latency99", "Latency999", "ServerCpuUsage", "SuccessfulRequestsPerSecond", "FailedRequestsPerSecond" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess" }, null, null, null) new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ScenarioResult), global::Grpc.Testing.ScenarioResult.Parser, new[]{ "Scenario", "Latencies", "ClientStats", "ServerStats", "ServerCores", "Summary", "ClientSuccess", "ServerSuccess", "RequestResults" }, null, null, null)
})); }));
} }
#endregion #endregion
@ -1641,6 +1645,7 @@ namespace Grpc.Testing {
PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null; PayloadConfig = other.payloadConfig_ != null ? other.PayloadConfig.Clone() : null;
coreList_ = other.coreList_.Clone(); coreList_ = other.coreList_.Clone();
otherServerApi_ = other.otherServerApi_; otherServerApi_ = other.otherServerApi_;
resourceQuotaSize_ = other.resourceQuotaSize_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1753,6 +1758,20 @@ namespace Grpc.Testing {
} }
} }
/// <summary>Field number for the "resource_quota_size" field.</summary>
public const int ResourceQuotaSizeFieldNumber = 1001;
private int resourceQuotaSize_;
/// <summary>
/// Buffer pool size (no buffer pool specified if unset)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int ResourceQuotaSize {
get { return resourceQuotaSize_; }
set {
resourceQuotaSize_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as ServerConfig); return Equals(other as ServerConfig);
@ -1774,6 +1793,7 @@ namespace Grpc.Testing {
if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false; if (!object.Equals(PayloadConfig, other.PayloadConfig)) return false;
if(!coreList_.Equals(other.coreList_)) return false; if(!coreList_.Equals(other.coreList_)) return false;
if (OtherServerApi != other.OtherServerApi) return false; if (OtherServerApi != other.OtherServerApi) return false;
if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
return true; return true;
} }
@ -1788,6 +1808,7 @@ namespace Grpc.Testing {
if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode(); if (payloadConfig_ != null) hash ^= PayloadConfig.GetHashCode();
hash ^= coreList_.GetHashCode(); hash ^= coreList_.GetHashCode();
if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode(); if (OtherServerApi.Length != 0) hash ^= OtherServerApi.GetHashCode();
if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
return hash; return hash;
} }
@ -1827,6 +1848,10 @@ namespace Grpc.Testing {
output.WriteRawTag(90); output.WriteRawTag(90);
output.WriteString(OtherServerApi); output.WriteString(OtherServerApi);
} }
if (ResourceQuotaSize != 0) {
output.WriteRawTag(200, 62);
output.WriteInt32(ResourceQuotaSize);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1854,6 +1879,9 @@ namespace Grpc.Testing {
if (OtherServerApi.Length != 0) { if (OtherServerApi.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi); size += 1 + pb::CodedOutputStream.ComputeStringSize(OtherServerApi);
} }
if (ResourceQuotaSize != 0) {
size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
}
return size; return size;
} }
@ -1890,6 +1918,9 @@ namespace Grpc.Testing {
if (other.OtherServerApi.Length != 0) { if (other.OtherServerApi.Length != 0) {
OtherServerApi = other.OtherServerApi; OtherServerApi = other.OtherServerApi;
} }
if (other.ResourceQuotaSize != 0) {
ResourceQuotaSize = other.ResourceQuotaSize;
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1939,6 +1970,10 @@ namespace Grpc.Testing {
OtherServerApi = input.ReadString(); OtherServerApi = input.ReadString();
break; break;
} }
case 8008: {
ResourceQuotaSize = input.ReadInt32();
break;
}
} }
} }
} }
@ -3117,6 +3152,9 @@ namespace Grpc.Testing {
latency95_ = other.latency95_; latency95_ = other.latency95_;
latency99_ = other.latency99_; latency99_ = other.latency99_;
latency999_ = other.latency999_; latency999_ = other.latency999_;
serverCpuUsage_ = other.serverCpuUsage_;
successfulRequestsPerSecond_ = other.successfulRequestsPerSecond_;
failedRequestsPerSecond_ = other.failedRequestsPerSecond_;
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3266,6 +3304,45 @@ namespace Grpc.Testing {
} }
} }
/// <summary>Field number for the "server_cpu_usage" field.</summary>
public const int ServerCpuUsageFieldNumber = 12;
private double serverCpuUsage_;
/// <summary>
/// server cpu usage percentage
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double ServerCpuUsage {
get { return serverCpuUsage_; }
set {
serverCpuUsage_ = value;
}
}
/// <summary>Field number for the "successful_requests_per_second" field.</summary>
public const int SuccessfulRequestsPerSecondFieldNumber = 13;
private double successfulRequestsPerSecond_;
/// <summary>
/// Number of requests that succeeded/failed
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double SuccessfulRequestsPerSecond {
get { return successfulRequestsPerSecond_; }
set {
successfulRequestsPerSecond_ = value;
}
}
/// <summary>Field number for the "failed_requests_per_second" field.</summary>
public const int FailedRequestsPerSecondFieldNumber = 14;
private double failedRequestsPerSecond_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public double FailedRequestsPerSecond {
get { return failedRequestsPerSecond_; }
set {
failedRequestsPerSecond_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as ScenarioResultSummary); return Equals(other as ScenarioResultSummary);
@ -3290,6 +3367,9 @@ namespace Grpc.Testing {
if (Latency95 != other.Latency95) return false; if (Latency95 != other.Latency95) return false;
if (Latency99 != other.Latency99) return false; if (Latency99 != other.Latency99) return false;
if (Latency999 != other.Latency999) return false; if (Latency999 != other.Latency999) return false;
if (ServerCpuUsage != other.ServerCpuUsage) return false;
if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
return true; return true;
} }
@ -3307,6 +3387,9 @@ namespace Grpc.Testing {
if (Latency95 != 0D) hash ^= Latency95.GetHashCode(); if (Latency95 != 0D) hash ^= Latency95.GetHashCode();
if (Latency99 != 0D) hash ^= Latency99.GetHashCode(); if (Latency99 != 0D) hash ^= Latency99.GetHashCode();
if (Latency999 != 0D) hash ^= Latency999.GetHashCode(); if (Latency999 != 0D) hash ^= Latency999.GetHashCode();
if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
return hash; return hash;
} }
@ -3361,6 +3444,18 @@ namespace Grpc.Testing {
output.WriteRawTag(89); output.WriteRawTag(89);
output.WriteDouble(Latency999); output.WriteDouble(Latency999);
} }
if (ServerCpuUsage != 0D) {
output.WriteRawTag(97);
output.WriteDouble(ServerCpuUsage);
}
if (SuccessfulRequestsPerSecond != 0D) {
output.WriteRawTag(105);
output.WriteDouble(SuccessfulRequestsPerSecond);
}
if (FailedRequestsPerSecond != 0D) {
output.WriteRawTag(113);
output.WriteDouble(FailedRequestsPerSecond);
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3399,6 +3494,15 @@ namespace Grpc.Testing {
if (Latency999 != 0D) { if (Latency999 != 0D) {
size += 1 + 8; size += 1 + 8;
} }
if (ServerCpuUsage != 0D) {
size += 1 + 8;
}
if (SuccessfulRequestsPerSecond != 0D) {
size += 1 + 8;
}
if (FailedRequestsPerSecond != 0D) {
size += 1 + 8;
}
return size; return size;
} }
@ -3440,6 +3544,15 @@ namespace Grpc.Testing {
if (other.Latency999 != 0D) { if (other.Latency999 != 0D) {
Latency999 = other.Latency999; Latency999 = other.Latency999;
} }
if (other.ServerCpuUsage != 0D) {
ServerCpuUsage = other.ServerCpuUsage;
}
if (other.SuccessfulRequestsPerSecond != 0D) {
SuccessfulRequestsPerSecond = other.SuccessfulRequestsPerSecond;
}
if (other.FailedRequestsPerSecond != 0D) {
FailedRequestsPerSecond = other.FailedRequestsPerSecond;
}
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3494,6 +3607,18 @@ namespace Grpc.Testing {
Latency999 = input.ReadDouble(); Latency999 = input.ReadDouble();
break; break;
} }
case 97: {
ServerCpuUsage = input.ReadDouble();
break;
}
case 105: {
SuccessfulRequestsPerSecond = input.ReadDouble();
break;
}
case 113: {
FailedRequestsPerSecond = input.ReadDouble();
break;
}
} }
} }
} }
@ -3535,6 +3660,7 @@ namespace Grpc.Testing {
Summary = other.summary_ != null ? other.Summary.Clone() : null; Summary = other.summary_ != null ? other.Summary.Clone() : null;
clientSuccess_ = other.clientSuccess_.Clone(); clientSuccess_ = other.clientSuccess_.Clone();
serverSuccess_ = other.serverSuccess_.Clone(); serverSuccess_ = other.serverSuccess_.Clone();
requestResults_ = other.requestResults_.Clone();
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3646,6 +3772,19 @@ namespace Grpc.Testing {
get { return serverSuccess_; } get { return serverSuccess_; }
} }
/// <summary>Field number for the "request_results" field.</summary>
public const int RequestResultsFieldNumber = 9;
private static readonly pb::FieldCodec<global::Grpc.Testing.RequestResultCount> _repeated_requestResults_codec
= pb::FieldCodec.ForMessage(74, global::Grpc.Testing.RequestResultCount.Parser);
private readonly pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> requestResults_ = new pbc::RepeatedField<global::Grpc.Testing.RequestResultCount>();
/// <summary>
/// Number of failed requests (one row per status code seen)
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Grpc.Testing.RequestResultCount> RequestResults {
get { return requestResults_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) { public override bool Equals(object other) {
return Equals(other as ScenarioResult); return Equals(other as ScenarioResult);
@ -3667,6 +3806,7 @@ namespace Grpc.Testing {
if (!object.Equals(Summary, other.Summary)) return false; if (!object.Equals(Summary, other.Summary)) return false;
if(!clientSuccess_.Equals(other.clientSuccess_)) return false; if(!clientSuccess_.Equals(other.clientSuccess_)) return false;
if(!serverSuccess_.Equals(other.serverSuccess_)) return false; if(!serverSuccess_.Equals(other.serverSuccess_)) return false;
if(!requestResults_.Equals(other.requestResults_)) return false;
return true; return true;
} }
@ -3681,6 +3821,7 @@ namespace Grpc.Testing {
if (summary_ != null) hash ^= Summary.GetHashCode(); if (summary_ != null) hash ^= Summary.GetHashCode();
hash ^= clientSuccess_.GetHashCode(); hash ^= clientSuccess_.GetHashCode();
hash ^= serverSuccess_.GetHashCode(); hash ^= serverSuccess_.GetHashCode();
hash ^= requestResults_.GetHashCode();
return hash; return hash;
} }
@ -3708,6 +3849,7 @@ namespace Grpc.Testing {
} }
clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec); clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec);
serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec); serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec);
requestResults_.WriteTo(output, _repeated_requestResults_codec);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3727,6 +3869,7 @@ namespace Grpc.Testing {
} }
size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec); size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec);
size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec); size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec);
size += requestResults_.CalculateSize(_repeated_requestResults_codec);
return size; return size;
} }
@ -3758,6 +3901,7 @@ namespace Grpc.Testing {
} }
clientSuccess_.Add(other.clientSuccess_); clientSuccess_.Add(other.clientSuccess_);
serverSuccess_.Add(other.serverSuccess_); serverSuccess_.Add(other.serverSuccess_);
requestResults_.Add(other.requestResults_);
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -3812,6 +3956,10 @@ namespace Grpc.Testing {
serverSuccess_.AddEntriesFrom(input, _repeated_serverSuccess_codec); serverSuccess_.AddEntriesFrom(input, _repeated_serverSuccess_codec);
break; break;
} }
case 74: {
requestResults_.AddEntriesFrom(input, _repeated_requestResults_codec);
break;
}
} }
} }
} }

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

Loading…
Cancel
Save