Merge branch 'master' of github.com:grpc/grpc

pull/23032/head
Rob Clevenger 5 years ago
commit 043be3d303
  1. 2
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 2
      .github/ISSUE_TEMPLATE/cleanup_request.md
  3. 2
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 2
      .github/ISSUE_TEMPLATE/question.md
  5. 2
      .github/pull_request_template.md
  6. 1
      .gitmodules
  7. 3
      BUILD
  8. 3
      BUILD.gn
  9. 2
      CMakeLists.txt
  10. 2
      Makefile
  11. 8
      bazel/grpc_deps.bzl
  12. 6
      build_autogenerated.yaml
  13. 1
      config.m4
  14. 1
      config.w32
  15. 4
      examples/php/composer.json
  16. 15
      examples/php/greeter_client.php
  17. 4
      gRPC-C++.podspec
  18. 5
      gRPC-Core.podspec
  19. 5
      grpc.gemspec
  20. 2
      grpc.gyp
  21. 4
      include/grpc/impl/codegen/port_platform.h
  22. 3
      package.xml
  23. 6
      src/compiler/cpp_plugin.h
  24. 6
      src/compiler/csharp_plugin.cc
  25. 6
      src/compiler/node_plugin.cc
  26. 6
      src/compiler/objective_c_plugin.cc
  27. 6
      src/compiler/php_plugin.cc
  28. 4
      src/compiler/python_generator.cc
  29. 4
      src/compiler/python_generator.h
  30. 6
      src/compiler/ruby_plugin.cc
  31. 93
      src/core/ext/filters/client_channel/client_channel.cc
  32. 5
      src/core/ext/filters/client_channel/client_channel_plugin.cc
  33. 29
      src/core/ext/filters/client_channel/health/health_check_client.cc
  34. 6
      src/core/ext/filters/client_channel/health/health_check_client.h
  35. 18
      src/core/ext/filters/client_channel/lb_policy.h
  36. 23
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  37. 25
      src/core/ext/filters/client_channel/lb_policy/xds/cds.cc
  38. 23
      src/core/ext/filters/client_channel/lb_policy/xds/eds.cc
  39. 2
      src/core/ext/filters/client_channel/lb_policy/xds/xds_routing.cc
  40. 9
      src/core/ext/filters/client_channel/resolver_result_parsing.cc
  41. 12
      src/core/ext/filters/client_channel/resolver_result_parsing.h
  42. 42
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  43. 4
      src/core/ext/filters/client_channel/resolving_lb_policy.h
  44. 88
      src/core/ext/filters/client_channel/service_config.cc
  45. 104
      src/core/ext/filters/client_channel/service_config.h
  46. 68
      src/core/ext/filters/client_channel/service_config_call_data.h
  47. 87
      src/core/ext/filters/client_channel/service_config_parser.cc
  48. 89
      src/core/ext/filters/client_channel/service_config_parser.h
  49. 69
      src/core/ext/filters/client_channel/xds/xds_bootstrap.cc
  50. 4
      src/core/ext/filters/client_channel/xds/xds_client.cc
  51. 46
      src/core/ext/filters/http/client/http_client_filter.cc
  52. 11
      src/core/ext/filters/message_size/message_size_filter.cc
  53. 8
      src/core/ext/filters/message_size/message_size_filter.h
  54. 16
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  55. 18
      src/core/ext/transport/inproc/inproc_transport.cc
  56. 17
      src/core/ext/upb-generated/google/protobuf/descriptor.upb.c
  57. 54
      src/core/ext/upb-generated/google/protobuf/descriptor.upb.h
  58. 27
      src/core/lib/channel/channel_args.cc
  59. 4
      src/core/lib/channel/channel_args.h
  60. 2
      src/core/lib/channel/context.h
  61. 24
      src/core/lib/channel/handshaker.cc
  62. 48
      src/core/lib/debug/stats.cc
  63. 2
      src/core/lib/debug/stats.h
  64. 23
      src/core/lib/gpr/string.cc
  65. 16
      src/core/lib/gpr/string.h
  66. 111
      src/core/lib/http/format_request.cc
  67. 38
      src/core/lib/iomgr/ev_epoll1_linux.cc
  68. 45
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  69. 108
      src/core/lib/surface/call_log_batch.cc
  70. 37
      src/core/lib/surface/completion_queue.cc
  71. 43
      src/core/lib/surface/event_string.cc
  72. 4
      src/core/lib/surface/event_string.h
  73. 5
      src/core/lib/transport/transport.h
  74. 163
      src/core/lib/transport/transport_op_string.cc
  75. 2
      src/cpp/Protobuf-C++.podspec
  76. 2
      src/csharp/Grpc.Core/SourceLink.csproj.include
  77. 2
      src/csharp/build/dependencies.props
  78. 2
      src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec
  79. 2
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  80. 2
      src/objective-c/!ProtoCompiler.podspec
  81. 2
      src/objective-c/tests/build_one_example.sh
  82. 17
      src/php/bin/generate_proto_php.sh
  83. 168
      src/php/lib/Grpc/RpcServer.php
  84. 6
      src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php
  85. 151
      src/php/tests/interop/xds_client.php
  86. 2
      src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi
  87. 1
      src/python/grpcio/grpc_core_dependencies.py
  88. 4
      src/python/grpcio_tests/tests/unit/_metadata_flags_test.py
  89. 2
      templates/grpc.gemspec.template
  90. 2
      templates/src/csharp/build/dependencies.props.template
  91. 2
      templates/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec.template
  92. 2
      templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.template
  93. 2
      templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
  94. 21
      test/core/bad_client/tests/large_metadata.cc
  95. 56
      test/core/channel/minimal_stack_is_minimal_test.cc
  96. 61
      test/core/client_channel/service_config_test.cc
  97. 78
      test/core/end2end/cq_verifier.cc
  98. 6
      test/core/end2end/tests/server_finishes_request.cc
  99. 6
      test/core/end2end/tests/simple_request.cc
  100. 22
      test/core/gpr/arena_test.cc
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,7 +2,7 @@
name: Report a bug
about: Create a report to help us improve
labels: kind/bug, priority/P2
assignees: yashykt
assignees: karthikravis
---

@ -2,7 +2,7 @@
name: Request a cleanup
about: Suggest a cleanup in our repository
labels: kind/internal cleanup, priority/P2
assignees: yashykt
assignees: karthikravis
---

@ -2,7 +2,7 @@
name: Request a feature
about: Suggest an idea for this project
labels: kind/enhancement, priority/P2
assignees: yashykt
assignees: karthikravis
---

@ -2,7 +2,7 @@
name: Ask a question
about: Ask a question
labels: kind/question, priority/P3
assignees: yashykt
assignees: karthikravis
---

@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be
-->
@yashykt
@karthikravis

1
.gitmodules vendored

@ -8,7 +8,6 @@
[submodule "third_party/protobuf"]
path = third_party/protobuf
url = https://github.com/google/protobuf.git
branch = 3.0.x
[submodule "third_party/gflags"]
path = third_party/gflags
url = https://github.com/gflags/gflags.git

@ -1044,6 +1044,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/retry_throttle.cc",
"src/core/ext/filters/client_channel/server_address.cc",
"src/core/ext/filters/client_channel/service_config.cc",
"src/core/ext/filters/client_channel/service_config_parser.cc",
"src/core/ext/filters/client_channel/subchannel.cc",
"src/core/ext/filters/client_channel/subchannel_pool_interface.cc",
],
@ -1074,6 +1075,8 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/retry_throttle.h",
"src/core/ext/filters/client_channel/server_address.h",
"src/core/ext/filters/client_channel/service_config.h",
"src/core/ext/filters/client_channel/service_config_call_data.h",
"src/core/ext/filters/client_channel/service_config_parser.h",
"src/core/ext/filters/client_channel/subchannel.h",
"src/core/ext/filters/client_channel/subchannel_interface.h",
"src/core/ext/filters/client_channel/subchannel_pool_interface.h",

@ -292,6 +292,9 @@ config("grpc_config") {
"src/core/ext/filters/client_channel/server_address.h",
"src/core/ext/filters/client_channel/service_config.cc",
"src/core/ext/filters/client_channel/service_config.h",
"src/core/ext/filters/client_channel/service_config_call_data.h",
"src/core/ext/filters/client_channel/service_config_parser.cc",
"src/core/ext/filters/client_channel/service_config_parser.h",
"src/core/ext/filters/client_channel/subchannel.cc",
"src/core/ext/filters/client_channel/subchannel.h",
"src/core/ext/filters/client_channel/subchannel_interface.h",

@ -1374,6 +1374,7 @@ add_library(grpc
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/service_config_parser.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/client_channel/xds/xds_api.cc
@ -2044,6 +2045,7 @@ add_library(grpc_unsecure
src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.cc
src/core/ext/filters/client_channel/service_config.cc
src/core/ext/filters/client_channel/service_config_parser.cc
src/core/ext/filters/client_channel/subchannel.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/client_channel/xds/xds_api.cc

@ -3676,6 +3676,7 @@ LIBGRPC_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/service_config_parser.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \
@ -4320,6 +4321,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/service_config_parser.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \

@ -154,11 +154,11 @@ def grpc_deps():
if "com_google_protobuf" not in native.existing_rules():
http_archive(
name = "com_google_protobuf",
sha256 = "2435b7fb83b8a608c24ca677907aa9a35e482a7f018e65ca69481b3c8c9f7caf",
strip_prefix = "protobuf-d0bfd5221182da1a7cc280f3337b5e41a89539cf",
sha256 = "efaf69303e01caccc2447064fc1832dfd23c0c130df0dc5fc98a13185bb7d1a7",
strip_prefix = "protobuf-678da4f76eb9168c9965afc2149944a66cd48546",
urls = [
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/protobuf/archive/d0bfd5221182da1a7cc280f3337b5e41a89539cf.tar.gz",
"https://github.com/google/protobuf/archive/d0bfd5221182da1a7cc280f3337b5e41a89539cf.tar.gz",
"https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/protobuf/archive/678da4f76eb9168c9965afc2149944a66cd48546.tar.gz",
"https://github.com/google/protobuf/archive/678da4f76eb9168c9965afc2149944a66cd48546.tar.gz",
],
)

@ -411,6 +411,8 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.h
- src/core/ext/filters/client_channel/server_address.h
- src/core/ext/filters/client_channel/service_config.h
- src/core/ext/filters/client_channel/service_config_call_data.h
- src/core/ext/filters/client_channel/service_config_parser.h
- src/core/ext/filters/client_channel/subchannel.h
- src/core/ext/filters/client_channel/subchannel_interface.h
- src/core/ext/filters/client_channel/subchannel_pool_interface.h
@ -791,6 +793,7 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.cc
- src/core/ext/filters/client_channel/service_config.cc
- src/core/ext/filters/client_channel/service_config_parser.cc
- src/core/ext/filters/client_channel/subchannel.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc
- src/core/ext/filters/client_channel/xds/xds_api.cc
@ -1331,6 +1334,8 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.h
- src/core/ext/filters/client_channel/server_address.h
- src/core/ext/filters/client_channel/service_config.h
- src/core/ext/filters/client_channel/service_config_call_data.h
- src/core/ext/filters/client_channel/service_config_parser.h
- src/core/ext/filters/client_channel/subchannel.h
- src/core/ext/filters/client_channel/subchannel_interface.h
- src/core/ext/filters/client_channel/subchannel_pool_interface.h
@ -1647,6 +1652,7 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.cc
- src/core/ext/filters/client_channel/service_config.cc
- src/core/ext/filters/client_channel/service_config_parser.cc
- src/core/ext/filters/client_channel/subchannel.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc
- src/core/ext/filters/client_channel/xds/xds_api.cc

@ -92,6 +92,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/filters/client_channel/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/service_config.cc \
src/core/ext/filters/client_channel/service_config_parser.cc \
src/core/ext/filters/client_channel/subchannel.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \

@ -61,6 +61,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
"src\\core\\ext\\filters\\client_channel\\server_address.cc " +
"src\\core\\ext\\filters\\client_channel\\service_config.cc " +
"src\\core\\ext\\filters\\client_channel\\service_config_parser.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_api.cc " +

@ -7,7 +7,9 @@
},
"autoload": {
"psr-4": {
"": "route_guide/"
"Routeguide\\": "route_guide/Routeguide/",
"GPBMetadata\\": ["GPBMetadata/","route_guide/GPBMetadata/"],
"Helloworld\\": "Helloworld/"
}
}
}

@ -21,11 +21,6 @@
require dirname(__FILE__).'/vendor/autoload.php';
@include_once dirname(__FILE__).'/Helloworld/GreeterClient.php';
@include_once dirname(__FILE__).'/Helloworld/HelloReply.php';
@include_once dirname(__FILE__).'/Helloworld/HelloRequest.php';
@include_once dirname(__FILE__).'/GPBMetadata/Helloworld.php';
function greet($name)
{
$client = new Helloworld\GreeterClient('localhost:50051', [
@ -34,10 +29,12 @@ function greet($name)
$request = new Helloworld\HelloRequest();
$request->setName($name);
list($reply, $status) = $client->SayHello($request)->wait();
$message = $reply->getMessage();
return $message;
if ($status->code !== Grpc\STATUS_OK) {
echo "ERROR: ".$status->code.", ".$status->details."\n";
exit(1);
}
echo $reply->getMessage()."\n";
}
$name = !empty($argv[1]) ? $argv[1] : 'world';
echo greet($name)."\n";
greet($name);

@ -261,6 +261,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/service_config_call_data.h',
'src/core/ext/filters/client_channel/service_config_parser.h',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_interface.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h',
@ -718,6 +720,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/service_config_call_data.h',
'src/core/ext/filters/client_channel/service_config_parser.h',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_interface.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h',

@ -276,6 +276,9 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/service_config_call_data.h',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/service_config_parser.h',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_interface.h',
@ -1082,6 +1085,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.h',
'src/core/ext/filters/client_channel/service_config.h',
'src/core/ext/filters/client_channel/service_config_call_data.h',
'src/core/ext/filters/client_channel/service_config_parser.h',
'src/core/ext/filters/client_channel/subchannel.h',
'src/core/ext/filters/client_channel/subchannel_interface.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h',

@ -32,7 +32,7 @@ Gem::Specification.new do |s|
s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.11'
s.add_dependency 'google-protobuf', '~> 3.12'
s.add_dependency 'googleapis-common-protos-types', '~> 1.0'
s.add_development_dependency 'bundler', '>= 1.9'
@ -198,6 +198,9 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/filters/client_channel/server_address.h )
s.files += %w( src/core/ext/filters/client_channel/service_config.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config.h )
s.files += %w( src/core/ext/filters/client_channel/service_config_call_data.h )
s.files += %w( src/core/ext/filters/client_channel/service_config_parser.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config_parser.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel_interface.h )

@ -487,6 +487,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',
@ -993,6 +994,7 @@
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',

@ -53,6 +53,8 @@
#define NOMINMAX
#endif /* NOMINMAX */
#include <windows.h>
#ifndef _WIN32_WINNT
#error \
"Please compile grpc with _WIN32_WINNT of at least 0x600 (aka Windows Vista)"
@ -63,8 +65,6 @@
#endif /* _WIN32_WINNT < 0x0600 */
#endif /* defined(_WIN32_WINNT) */
#include <windows.h>
#ifdef GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED
#undef GRPC_WIN32_LEAN_AND_MEAN_WAS_NOT_DEFINED
#undef WIN32_LEAN_AND_MEAN

@ -178,6 +178,9 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/server_address.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_call_data.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/service_config_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_interface.h" role="src" />

@ -34,10 +34,14 @@ class CppGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
CppGrpcGenerator() {}
virtual ~CppGrpcGenerator() {}
uint64_t GetSupportedFeatures() const override {
return FEATURE_PROTO3_OPTIONAL;
}
virtual bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const {
grpc::string* error) const override {
if (file->options().cc_generic_services()) {
*error =
"cpp grpc proto compiler plugin does not work with generic "

@ -29,10 +29,14 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
CSharpGrpcGenerator() {}
~CSharpGrpcGenerator() {}
uint64_t GetSupportedFeatures() const override {
return FEATURE_PROTO3_OPTIONAL;
}
bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const {
grpc::string* error) const override {
std::vector<std::pair<grpc::string, grpc::string> > options;
grpc::protobuf::compiler::ParseGeneratorParameter(parameter, &options);

@ -32,10 +32,14 @@ class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
NodeGrpcGenerator() {}
~NodeGrpcGenerator() {}
uint64_t GetSupportedFeatures() const override {
return FEATURE_PROTO3_OPTIONAL;
}
bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const {
grpc::string* error) const override {
grpc_node_generator::Parameters generator_parameters;
generator_parameters.minimum_node_version = 4;

@ -71,10 +71,14 @@ class ObjectiveCGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
virtual ~ObjectiveCGrpcGenerator() {}
public:
uint64_t GetSupportedFeatures() const override {
return FEATURE_PROTO3_OPTIONAL;
}
virtual bool Generate(const grpc::protobuf::FileDescriptor* file,
const ::grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
::grpc::string* error) const {
::grpc::string* error) const override {
if (file->service_count() == 0) {
// No services. Do nothing.
return true;

@ -33,10 +33,14 @@ class PHPGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
PHPGrpcGenerator() {}
~PHPGrpcGenerator() {}
uint64_t GetSupportedFeatures() const override {
return FEATURE_PROTO3_OPTIONAL;
}
bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const {
grpc::string* error) const override {
if (file->service_count() == 0) {
return true;
}

@ -875,6 +875,10 @@ static bool ParseParameters(const grpc::string& parameter,
return true;
}
uint64_t PythonGrpcGenerator::GetSupportedFeatures() const {
return FEATURE_PROTO3_OPTIONAL;
}
bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
const grpc::string& parameter,
GeneratorContext* context,

@ -44,10 +44,12 @@ class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
PythonGrpcGenerator(const GeneratorConfiguration& config);
~PythonGrpcGenerator();
uint64_t GetSupportedFeatures() const override;
bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& parameter,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* error) const;
grpc::string* error) const override;
private:
GeneratorConfiguration config_;

@ -29,10 +29,14 @@ class RubyGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
RubyGrpcGenerator() {}
~RubyGrpcGenerator() {}
uint64_t GetSupportedFeatures() const override {
return FEATURE_PROTO3_OPTIONAL;
}
bool Generate(const grpc::protobuf::FileDescriptor* file,
const grpc::string& /*parameter*/,
grpc::protobuf::compiler::GeneratorContext* context,
grpc::string* /*error*/) const {
grpc::string* /*error*/) const override {
grpc::string code = grpc_ruby_generator::GetServices(file);
if (code.size() == 0) {
return true; // don't generate a file if there are no services

@ -50,6 +50,7 @@
#include "src/core/ext/filters/client_channel/resolving_lb_policy.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/service_config_call_data.h"
#include "src/core/ext/filters/client_channel/subchannel.h"
#include "src/core/ext/filters/deadline/deadline_filter.h"
#include "src/core/lib/backoff/backoff.h"
@ -441,6 +442,12 @@ class CallData {
return calld_->backend_metric_data_;
}
absl::string_view ExperimentalGetCallAttribute(const char* key) override {
auto it = calld_->call_attributes_.find(key);
if (it == calld_->call_attributes_.end()) return absl::string_view();
return it->second;
}
private:
CallData* calld_;
};
@ -760,8 +767,8 @@ class CallData {
grpc_call_context_element* call_context_;
RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
ServiceConfig::CallData service_config_call_data_;
const ClientChannelMethodParsedConfig* method_params_ = nullptr;
std::map<const char*, absl::string_view> call_attributes_;
RefCountedPtr<SubchannelCall> subchannel_call_;
@ -3164,9 +3171,10 @@ void CallData::OnComplete(void* arg, grpc_error* error) {
ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
CallData* calld = static_cast<CallData*>(elem->call_data);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
char* batch_str = grpc_transport_stream_op_batch_string(&batch_data->batch);
gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
chand, calld, grpc_error_string(error),
grpc_transport_stream_op_batch_string(&batch_data->batch).c_str());
chand, calld, grpc_error_string(error), batch_str);
gpr_free(batch_str);
}
SubchannelCallRetryState* retry_state =
static_cast<SubchannelCallRetryState*>(
@ -3239,8 +3247,10 @@ void CallData::AddClosureForSubchannelBatch(
GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner,
batch, grpc_schedule_on_exec_ctx);
if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) {
char* batch_str = grpc_transport_stream_op_batch_string(batch);
gpr_log(GPR_INFO, "chand=%p calld=%p: starting subchannel batch: %s", chand,
this, grpc_transport_stream_op_batch_string(batch).c_str());
this, batch_str);
gpr_free(batch_str);
}
closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE,
"start_subchannel_batch");
@ -3753,45 +3763,52 @@ void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
chand, this);
}
// Store a ref to the service_config in service_config_call_data_. Also, save
// a pointer to this in the call_context so that all future filters can access
// it.
service_config_call_data_ =
ServiceConfig::CallData(chand->service_config(), path_);
if (service_config_call_data_.service_config() != nullptr) {
call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value =
&service_config_call_data_;
auto service_config = chand->service_config();
if (service_config != nullptr) {
// Create a ServiceConfigCallData for the call. This stores a ref to the
// ServiceConfig and caches the right set of parsed configs to use for
// the call. The MethodConfig will store itself in the call context,
// so that it can be accessed by filters in the subchannel, and it
// will be cleaned up when the call ends.
const auto* method_params_vector =
service_config->GetMethodParsedConfigVector(path_);
auto* service_config_call_data = arena_->New<ServiceConfigCallData>(
std::move(service_config), method_params_vector, call_context_);
// Apply our own method params to the call.
method_params_ = static_cast<ClientChannelMethodParsedConfig*>(
service_config_call_data_.GetMethodParsedConfig(
service_config_call_data->GetMethodParsedConfig(
internal::ClientChannelServiceConfigParser::ParserIndex()));
}
retry_throttle_data_ = chand->retry_throttle_data();
if (method_params_ != nullptr) {
// If the deadline from the service config is shorter than the one
// from the client API, reset the deadline timer.
if (chand->deadline_checking_enabled() && method_params_->timeout() != 0) {
const grpc_millis per_method_deadline =
grpc_cycle_counter_to_millis_round_up(call_start_time_) +
method_params_->timeout();
if (per_method_deadline < deadline_) {
deadline_ = per_method_deadline;
grpc_deadline_state_reset(elem, deadline_);
if (method_params_ != nullptr) {
// If the deadline from the service config is shorter than the one
// from the client API, reset the deadline timer.
if (chand->deadline_checking_enabled() &&
method_params_->timeout() != 0) {
const grpc_millis per_method_deadline =
grpc_cycle_counter_to_millis_round_up(call_start_time_) +
method_params_->timeout();
if (per_method_deadline < deadline_) {
deadline_ = per_method_deadline;
grpc_deadline_state_reset(elem, deadline_);
}
}
}
// If the service config set wait_for_ready and the application
// did not explicitly set it, use the value from the service config.
uint32_t* send_initial_metadata_flags =
&pending_batches_[0]
.batch->payload->send_initial_metadata.send_initial_metadata_flags;
if (method_params_->wait_for_ready().has_value() &&
!(*send_initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) {
if (method_params_->wait_for_ready().value()) {
*send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
*send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
// If the service config set wait_for_ready and the application
// did not explicitly set it, use the value from the service config.
uint32_t* send_initial_metadata_flags =
&pending_batches_[0]
.batch->payload->send_initial_metadata
.send_initial_metadata_flags;
if (method_params_->wait_for_ready().has_value() &&
!(*send_initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) {
if (method_params_->wait_for_ready().value()) {
*send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else {
*send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
}
}
}
// Set retry throttle data for call.
retry_throttle_data_ = chand->retry_throttle_data();
}
// If no retry policy, disable retries.
// TODO(roth): Remove this when adding support for transparent retries.

@ -35,6 +35,7 @@
#include "src/core/ext/filters/client_channel/resolver_registry.h"
#include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
#include "src/core/ext/filters/client_channel/retry_throttle.h"
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/lib/surface/channel_init.h"
static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
@ -43,7 +44,7 @@ static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
}
void grpc_client_channel_init(void) {
grpc_core::ServiceConfig::Init();
grpc_core::ServiceConfigParser::Init();
grpc_core::internal::ClientChannelServiceConfigParser::Register();
grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry();
grpc_core::ResolverRegistry::Builder::InitRegistry();
@ -65,5 +66,5 @@ void grpc_client_channel_shutdown(void) {
grpc_core::internal::ServerRetryThrottleMap::Shutdown();
grpc_core::ResolverRegistry::Builder::ShutdownRegistry();
grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry();
grpc_core::ServiceConfig::Shutdown();
grpc_core::ServiceConfigParser::Shutdown();
}

@ -125,8 +125,7 @@ void HealthCheckClient::StartCallLocked() {
call_state_->StartCall();
}
void HealthCheckClient::StartRetryTimer() {
MutexLock lock(&mu_);
void HealthCheckClient::StartRetryTimerLocked() {
SetHealthStatusLocked(GRPC_CHANNEL_TRANSIENT_FAILURE,
"health check call failed; will retry after backoff");
grpc_millis next_try = retry_backoff_.NextAttemptTime();
@ -297,14 +296,7 @@ void HealthCheckClient::CallState::StartCall() {
"checking call on subchannel (%s); will retry",
health_check_client_.get(), this, grpc_error_string(error));
GRPC_ERROR_UNREF(error);
// Schedule instead of running directly, since we must not be
// holding health_check_client_->mu_ when CallEnded() is called.
call_->Ref(DEBUG_LOCATION, "call_end_closure").release();
ExecCtx::Run(
DEBUG_LOCATION,
GRPC_CLOSURE_INIT(&batch_.handler_private.closure, CallEndedRetry, this,
grpc_schedule_on_exec_ctx),
GRPC_ERROR_NONE);
CallEndedLocked(/*retry=*/true);
return;
}
// Initialize payload and batch.
@ -582,18 +574,11 @@ void HealthCheckClient::CallState::RecvTrailingMetadataReady(
kErrorMessage);
retry = false;
}
self->CallEnded(retry);
}
void HealthCheckClient::CallState::CallEndedRetry(void* arg,
grpc_error* /*error*/) {
HealthCheckClient::CallState* self =
static_cast<HealthCheckClient::CallState*>(arg);
self->CallEnded(true /* retry */);
self->call_->Unref(DEBUG_LOCATION, "call_end_closure");
MutexLock lock(&self->health_check_client_->mu_);
self->CallEndedLocked(retry);
}
void HealthCheckClient::CallState::CallEnded(bool retry) {
void HealthCheckClient::CallState::CallEndedLocked(bool retry) {
// If this CallState is still in use, this call ended because of a failure,
// so we need to stop using it and optionally create a new one.
// Otherwise, we have deliberately ended this call, and no further action
@ -606,10 +591,10 @@ void HealthCheckClient::CallState::CallEnded(bool retry) {
// If the call fails after we've gotten a successful response, reset
// the backoff and restart the call immediately.
health_check_client_->retry_backoff_.Reset();
health_check_client_->StartCall();
health_check_client_->StartCallLocked();
} else {
// If the call failed without receiving any messages, retry later.
health_check_client_->StartRetryTimer();
health_check_client_->StartRetryTimerLocked();
}
}
}

@ -72,8 +72,8 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
void StartBatch(grpc_transport_stream_op_batch* batch);
static void StartBatchInCallCombiner(void* arg, grpc_error* error);
static void CallEndedRetry(void* arg, grpc_error* error);
void CallEnded(bool retry);
// Requires holding health_check_client_->mu_.
void CallEndedLocked(bool retry);
static void OnComplete(void* arg, grpc_error* error);
static void RecvInitialMetadataReady(void* arg, grpc_error* error);
@ -143,7 +143,7 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> {
void StartCall();
void StartCallLocked(); // Requires holding mu_.
void StartRetryTimer();
void StartRetryTimerLocked(); // Requires holding mu_.
static void OnRetryTimer(void* arg, grpc_error* error);
void SetHealthStatus(grpc_connectivity_state state, const char* reason);

@ -116,7 +116,17 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// Returns the backend metric data returned by the server for the call,
/// or null if no backend metric data was returned.
// TODO(roth): Move this out of CallState, since it should not be
// accessible to the picker, only to the recv_trailing_metadata_ready
// callback. It should instead be in its own interface.
virtual const BackendMetricData* GetBackendMetricData() = 0;
/// EXPERIMENTAL API.
/// Returns the value of the call attribute \a key.
/// Keys are static strings, so an attribute can be accessed by an LB
/// policy implementation only if it knows about the internal key.
/// Returns a null string_view if key not found.
virtual absl::string_view ExperimentalGetCallAttribute(const char* key) = 0;
};
/// Interface for accessing metadata.
@ -186,7 +196,7 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// call to the chosen backend.
MetadataInterface* initial_metadata;
/// An interface for accessing call state. Can be used to allocate
/// data associated with the call in an efficient way.
/// memory associated with the call in an efficient way.
CallState* call_state;
};
@ -228,6 +238,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// does not take ownership, so any data that needs to be used after
/// returning must be copied.
/// The call state can be used to obtain backend metric data.
// TODO(roth): The arguments to this callback should be moved into a
// struct, so that we can later add new fields without breaking
// existing implementations.
std::function<void(grpc_error*, MetadataInterface*, CallState*)>
recv_trailing_metadata_ready;
};
@ -256,9 +269,6 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> {
/// A proxy object implemented by the client channel and used by the
/// LB policy to communicate with the channel.
// TODO(juanlishen): Consider adding a mid-layer subclass that helps handle
// things like swapping in pending policy when it's ready. Currently, we are
// duplicating the logic in many subclasses.
class ChannelControlHelper {
public:
ChannelControlHelper() = default;

@ -65,8 +65,6 @@
#include <string.h>
#include "absl/container/inlined_vector.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/byte_buffer_reader.h>
#include <grpc/grpc.h>
@ -237,7 +235,7 @@ class GrpcLb : public LoadBalancingPolicy {
const std::vector<GrpcLbServer>& serverlist() const { return serverlist_; }
// Returns a text representation suitable for logging.
std::string AsText() const;
grpc_core::UniquePtr<char> AsText() const;
// Extracts all non-drop entries into a ServerAddressList.
ServerAddressList GetServerAddressList(
@ -447,8 +445,9 @@ void ParseServer(const GrpcLbServer& server, grpc_resolved_address* addr) {
}
}
std::string GrpcLb::Serverlist::AsText() const {
std::vector<std::string> entries;
grpc_core::UniquePtr<char> GrpcLb::Serverlist::AsText() const {
gpr_strvec entries;
gpr_strvec_init(&entries);
for (size_t i = 0; i < serverlist_.size(); ++i) {
const GrpcLbServer& server = serverlist_[i];
std::string ipport;
@ -459,10 +458,14 @@ std::string GrpcLb::Serverlist::AsText() const {
ParseServer(server, &addr);
ipport = grpc_sockaddr_to_string(&addr, false);
}
entries.push_back(absl::StrFormat(" %" PRIuPTR ": %s token=%s\n", i,
ipport, server.load_balance_token));
char* entry;
gpr_asprintf(&entry, " %" PRIuPTR ": %s token=%s\n", i, ipport.c_str(),
server.load_balance_token);
gpr_strvec_add(&entries, entry);
}
return absl::StrJoin(entries, "");
grpc_core::UniquePtr<char> result(gpr_strvec_flatten(&entries, nullptr));
gpr_strvec_destroy(&entries);
return result;
}
// vtables for channel args for LB token and client stats.
@ -1054,12 +1057,14 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() {
auto serverlist_wrapper =
MakeRefCounted<Serverlist>(std::move(response.serverlist));
if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) {
grpc_core::UniquePtr<char> serverlist_text =
serverlist_wrapper->AsText();
gpr_log(GPR_INFO,
"[grpclb %p] lb_calld=%p: Serverlist with %" PRIuPTR
" servers received:\n%s",
grpclb_policy(), this,
serverlist_wrapper->serverlist().size(),
serverlist_wrapper->AsText().c_str());
serverlist_text.get());
}
seen_serverlist_ = true;
// Start sending client load report only after we start using the

@ -215,22 +215,17 @@ void CdsLb::ClusterWatcher::OnError(grpc_error* error) {
}
void CdsLb::ClusterWatcher::OnResourceDoesNotExist() {
gpr_log(GPR_ERROR, "[cdslb %p] CDS resource for %s does not exist",
gpr_log(GPR_ERROR,
"[cdslb %p] CDS resource for %s does not exist -- reporting "
"TRANSIENT_FAILURE",
parent_.get(), parent_->config_->cluster().c_str());
// Go into TRANSIENT_FAILURE if we have not yet created the child
// policy (i.e., we have not yet received data from xds). Otherwise,
// we keep running with the data we had previously.
// TODO(roth): Once traffic splitting is implemented, this should be
// fixed to report TRANSIENT_FAILURE unconditionally.
if (parent_->child_policy_ == nullptr) {
parent_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE,
absl::make_unique<TransientFailurePicker>(
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("CDS resource \"", parent_->config_->cluster(),
"\" does not exist")
.c_str())));
}
parent_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE,
absl::make_unique<TransientFailurePicker>(
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("CDS resource \"", parent_->config_->cluster(),
"\" does not exist")
.c_str())));
}
//

@ -342,20 +342,15 @@ class EdsLb::EndpointWatcher : public XdsClient::EndpointWatcherInterface {
}
void OnResourceDoesNotExist() override {
gpr_log(GPR_ERROR, "[edslb %p] EDS resource does not exist",
eds_policy_.get());
// Go into TRANSIENT_FAILURE if we have not yet created the child
// policy (i.e., we have not yet received data from xds). Otherwise,
// we keep running with the data we had previously.
// TODO(roth): Once traffic splitting is implemented, this should be
// fixed to report TRANSIENT_FAILURE unconditionally.
if (eds_policy_->child_policy_ == nullptr) {
eds_policy_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE,
absl::make_unique<TransientFailurePicker>(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"EDS resource does not exist")));
}
gpr_log(
GPR_ERROR,
"[edslb %p] EDS resource does not exist -- reporting TRANSIENT_FAILURE",
eds_policy_.get());
eds_policy_->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE,
absl::make_unique<TransientFailurePicker>(
GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"EDS resource does not exist")));
}
private:

@ -712,7 +712,7 @@ class XdsRoutingLbFactory : public LoadBalancingPolicyFactory {
"value should be of type object"));
return error_list;
}
auto it = json.object_value().find("child_policy");
auto it = json.object_value().find("childPolicy");
if (it == json.object_value().end()) {
error_list.push_back(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("did not find childPolicy"));

@ -54,8 +54,9 @@ size_t ClientChannelServiceConfigParser::ParserIndex() {
}
void ClientChannelServiceConfigParser::Register() {
g_client_channel_service_config_parser_index = ServiceConfig::RegisterParser(
absl::make_unique<ClientChannelServiceConfigParser>());
g_client_channel_service_config_parser_index =
ServiceConfigParser::RegisterParser(
absl::make_unique<ClientChannelServiceConfigParser>());
}
namespace {
@ -312,7 +313,7 @@ const char* ParseHealthCheckConfig(const Json& field, grpc_error** error) {
} // namespace
std::unique_ptr<ServiceConfig::ParsedConfig>
std::unique_ptr<ServiceConfigParser::ParsedConfig>
ClientChannelServiceConfigParser::ParseGlobalParams(const Json& json,
grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
@ -393,7 +394,7 @@ ClientChannelServiceConfigParser::ParseGlobalParams(const Json& json,
return nullptr;
}
std::unique_ptr<ServiceConfig::ParsedConfig>
std::unique_ptr<ServiceConfigParser::ParsedConfig>
ClientChannelServiceConfigParser::ParsePerMethodParams(const Json& json,
grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);

@ -38,7 +38,8 @@
namespace grpc_core {
namespace internal {
class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
class ClientChannelGlobalParsedConfig
: public ServiceConfigParser::ParsedConfig {
public:
struct RetryThrottling {
intptr_t max_milli_tokens = 0;
@ -78,7 +79,8 @@ class ClientChannelGlobalParsedConfig : public ServiceConfig::ParsedConfig {
const char* health_check_service_name_;
};
class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
class ClientChannelMethodParsedConfig
: public ServiceConfigParser::ParsedConfig {
public:
struct RetryPolicy {
int max_attempts = 0;
@ -107,12 +109,12 @@ class ClientChannelMethodParsedConfig : public ServiceConfig::ParsedConfig {
std::unique_ptr<RetryPolicy> retry_policy_;
};
class ClientChannelServiceConfigParser : public ServiceConfig::Parser {
class ClientChannelServiceConfigParser : public ServiceConfigParser::Parser {
public:
std::unique_ptr<ServiceConfig::ParsedConfig> ParseGlobalParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
const Json& json, grpc_error** error) override;
std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
const Json& json, grpc_error** error) override;
static size_t ParserIndex();

@ -26,9 +26,6 @@
#include <stdio.h>
#include <string.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -244,6 +241,7 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
}
// Creates a new LB policy.
// Updates trace_strings to indicate what was done.
OrphanablePtr<LoadBalancingPolicy>
ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
const grpc_channel_args& args) {
@ -267,21 +265,31 @@ void ResolvingLoadBalancingPolicy::MaybeAddTraceMessagesForAddressChangesLocked(
bool resolution_contains_addresses, TraceStringVector* trace_strings) {
if (!resolution_contains_addresses &&
previous_resolution_contained_addresses_) {
trace_strings->push_back("Address list became empty");
trace_strings->push_back(gpr_strdup("Address list became empty"));
} else if (resolution_contains_addresses &&
!previous_resolution_contained_addresses_) {
trace_strings->push_back("Address list became non-empty");
trace_strings->push_back(gpr_strdup("Address list became non-empty"));
}
previous_resolution_contained_addresses_ = resolution_contains_addresses;
}
void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
const TraceStringVector& trace_strings) const {
if (!trace_strings.empty()) {
std::string message =
absl::StrCat("Resolution event: ", absl::StrJoin(trace_strings, ", "));
TraceStringVector* trace_strings) const {
if (!trace_strings->empty()) {
gpr_strvec v;
gpr_strvec_init(&v);
gpr_strvec_add(&v, gpr_strdup("Resolution event: "));
bool is_first = 1;
for (size_t i = 0; i < trace_strings->size(); ++i) {
if (!is_first) gpr_strvec_add(&v, gpr_strdup(", "));
is_first = false;
gpr_strvec_add(&v, (*trace_strings)[i]);
}
size_t len = 0;
grpc_core::UniquePtr<char> message(gpr_strvec_flatten(&v, &len));
channel_control_helper()->AddTraceEvent(ChannelControlHelper::TRACE_INFO,
message);
absl::string_view(message.get()));
gpr_strvec_destroy(&v);
}
}
@ -306,7 +314,7 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
// Process the resolver result.
RefCountedPtr<LoadBalancingPolicy::Config> lb_policy_config;
bool service_config_changed = false;
std::string service_config_error_string;
char* service_config_error_string = nullptr;
if (process_resolver_result_ != nullptr) {
grpc_error* service_config_error = GRPC_ERROR_NONE;
bool no_valid_service_config = false;
@ -314,7 +322,8 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
process_resolver_result_user_data_, result, &lb_policy_config,
&service_config_error, &no_valid_service_config);
if (service_config_error != GRPC_ERROR_NONE) {
service_config_error_string = grpc_error_string(service_config_error);
service_config_error_string =
gpr_strdup(grpc_error_string(service_config_error));
if (no_valid_service_config) {
// We received an invalid service config and we don't have a
// fallback service config.
@ -335,14 +344,15 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
if (service_config_changed) {
// TODO(ncteisen): might be worth somehow including a snippet of the
// config in the trace, at the risk of bloating the trace logs.
trace_strings.push_back("Service config changed");
trace_strings.push_back(gpr_strdup("Service config changed"));
}
if (!service_config_error_string.empty()) {
trace_strings.push_back(service_config_error_string.c_str());
if (service_config_error_string != nullptr) {
trace_strings.push_back(service_config_error_string);
service_config_error_string = nullptr;
}
MaybeAddTraceMessagesForAddressChangesLocked(resolution_contains_addresses,
&trace_strings);
ConcatenateAndAddChannelTraceLocked(trace_strings);
ConcatenateAndAddChannelTraceLocked(&trace_strings);
}
} // namespace grpc_core

@ -81,7 +81,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void ResetBackoffLocked() override;
private:
using TraceStringVector = absl::InlinedVector<const char*, 3>;
using TraceStringVector = absl::InlinedVector<char*, 3>;
class ResolverResultHandler;
class ResolvingControlHelper;
@ -99,7 +99,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void MaybeAddTraceMessagesForAddressChangesLocked(
bool resolution_contains_addresses, TraceStringVector* trace_strings);
void ConcatenateAndAddChannelTraceLocked(
const TraceStringVector& trace_strings) const;
TraceStringVector* trace_strings) const;
void OnResolverResultChangedLocked(Resolver::Result result);
// Passed in from caller at construction time.

@ -18,28 +18,18 @@
#include "src/core/ext/filters/client_channel/service_config.h"
#include <string.h>
#include <string>
#include "absl/strings/str_cat.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/gpr/string.h"
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/lib/json/json.h"
#include "src/core/lib/slice/slice_internal.h"
namespace grpc_core {
namespace {
typedef absl::InlinedVector<std::unique_ptr<ServiceConfig::Parser>,
ServiceConfig::kNumPreallocatedParsers>
ServiceConfigParserList;
ServiceConfigParserList* g_registered_parsers;
} // namespace
RefCountedPtr<ServiceConfig> ServiceConfig::Create(
absl::string_view json_string, grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr);
@ -59,21 +49,16 @@ ServiceConfig::ServiceConfig(std::string json_string, Json json,
GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON value is not an object");
return;
}
grpc_error* error_list[2];
int error_count = 0;
grpc_error* global_error = ParseGlobalParams();
std::vector<grpc_error*> error_list;
grpc_error* global_error = GRPC_ERROR_NONE;
parsed_global_configs_ =
ServiceConfigParser::ParseGlobalParameters(json_, &global_error);
if (global_error != GRPC_ERROR_NONE) error_list.push_back(global_error);
grpc_error* local_error = ParsePerMethodParams();
if (global_error != GRPC_ERROR_NONE) {
error_list[error_count++] = global_error;
}
if (local_error != GRPC_ERROR_NONE) {
error_list[error_count++] = local_error;
}
if (error_count > 0) {
*error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Service config parsing error", error_list, error_count);
GRPC_ERROR_UNREF(global_error);
GRPC_ERROR_UNREF(local_error);
if (local_error != GRPC_ERROR_NONE) error_list.push_back(local_error);
if (!error_list.empty()) {
*error = GRPC_ERROR_CREATE_FROM_VECTOR("Service config parsing error",
&error_list);
}
}
@ -83,34 +68,18 @@ ServiceConfig::~ServiceConfig() {
}
}
grpc_error* ServiceConfig::ParseGlobalParams() {
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < g_registered_parsers->size(); i++) {
grpc_error* parser_error = GRPC_ERROR_NONE;
auto parsed_obj =
(*g_registered_parsers)[i]->ParseGlobalParams(json_, &parser_error);
if (parser_error != GRPC_ERROR_NONE) {
error_list.push_back(parser_error);
}
parsed_global_configs_.push_back(std::move(parsed_obj));
}
return GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
}
grpc_error* ServiceConfig::ParseJsonMethodConfig(const Json& json) {
// Parse method config with each registered parser.
auto objs_vector = absl::make_unique<ParsedConfigVector>();
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < g_registered_parsers->size(); i++) {
grpc_error* parser_error = GRPC_ERROR_NONE;
auto parsed_obj =
(*g_registered_parsers)[i]->ParsePerMethodParams(json, &parser_error);
if (parser_error != GRPC_ERROR_NONE) {
error_list.push_back(parser_error);
}
objs_vector->push_back(std::move(parsed_obj));
// Parse method config with each registered parser.
auto parsed_configs =
absl::make_unique<ServiceConfigParser::ParsedConfigVector>();
grpc_error* parser_error = GRPC_ERROR_NONE;
*parsed_configs =
ServiceConfigParser::ParsePerMethodParameters(json, &parser_error);
if (parser_error != GRPC_ERROR_NONE) {
error_list.push_back(parser_error);
}
parsed_method_config_vectors_storage_.push_back(std::move(objs_vector));
parsed_method_config_vectors_storage_.push_back(std::move(parsed_configs));
const auto* vector_ptr = parsed_method_config_vectors_storage_.back().get();
// Add an entry for each path.
bool found_name = false;
@ -231,7 +200,7 @@ std::string ServiceConfig::ParseJsonMethodName(const Json& json,
method_name == nullptr ? "" : *method_name);
}
const ServiceConfig::ParsedConfigVector*
const ServiceConfigParser::ParsedConfigVector*
ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) const {
// Try looking up the full path in the map.
auto it = parsed_method_configs_map_.find(path);
@ -249,19 +218,4 @@ ServiceConfig::GetMethodParsedConfigVector(const grpc_slice& path) const {
return default_method_config_vector_;
}
size_t ServiceConfig::RegisterParser(std::unique_ptr<Parser> parser) {
g_registered_parsers->push_back(std::move(parser));
return g_registered_parsers->size() - 1;
}
void ServiceConfig::Init() {
GPR_ASSERT(g_registered_parsers == nullptr);
g_registered_parsers = new ServiceConfigParserList();
}
void ServiceConfig::Shutdown() {
delete g_registered_parsers;
g_registered_parsers = nullptr;
}
} // namespace grpc_core

@ -26,6 +26,7 @@
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/string_util.h>
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h"
@ -58,75 +59,10 @@
namespace grpc_core {
// TODO(roth): Consider stripping this down further to the completely minimal
// interface requied to be exposed as part of the resolver API.
class ServiceConfig : public RefCounted<ServiceConfig> {
public:
/// This is the base class that all service config parsers MUST use to store
/// parsed service config data.
class ParsedConfig {
public:
virtual ~ParsedConfig() = default;
};
/// This is the base class that all service config parsers should derive from.
class Parser {
public:
virtual ~Parser() = default;
virtual std::unique_ptr<ParsedConfig> ParseGlobalParams(
const Json& /* json */, grpc_error** error) {
// Avoid unused parameter warning on debug-only parameter
(void)error;
GPR_DEBUG_ASSERT(error != nullptr);
return nullptr;
}
virtual std::unique_ptr<ParsedConfig> ParsePerMethodParams(
const Json& /* json */, grpc_error** error) {
// Avoid unused parameter warning on debug-only parameter
(void)error;
GPR_DEBUG_ASSERT(error != nullptr);
return nullptr;
}
};
static constexpr int kNumPreallocatedParsers = 4;
typedef absl::InlinedVector<std::unique_ptr<ParsedConfig>,
kNumPreallocatedParsers>
ParsedConfigVector;
/// When a service config is applied to a call in the client_channel_filter,
/// we create an instance of this object and store it in the call_data for
/// client_channel. A pointer to this object is also stored in the
/// call_context, so that future filters can easily access method and global
/// parameters for the call.
class CallData {
public:
CallData() = default;
CallData(RefCountedPtr<ServiceConfig> svc_cfg, const grpc_slice& path)
: service_config_(std::move(svc_cfg)) {
if (service_config_ != nullptr) {
method_params_vector_ =
service_config_->GetMethodParsedConfigVector(path);
}
}
ServiceConfig* service_config() { return service_config_.get(); }
ParsedConfig* GetMethodParsedConfig(size_t index) const {
return method_params_vector_ != nullptr
? (*method_params_vector_)[index].get()
: nullptr;
}
ParsedConfig* GetGlobalParsedConfig(size_t index) const {
return service_config_->GetGlobalParsedConfig(index);
}
private:
RefCountedPtr<ServiceConfig> service_config_;
const ParsedConfigVector* method_params_vector_ = nullptr;
};
/// Creates a new service config from parsing \a json_string.
/// Returns null on parse error.
static RefCountedPtr<ServiceConfig> Create(absl::string_view json_string,
@ -140,7 +76,7 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
/// Retrieves the global parsed config at index \a index. The
/// lifetime of the returned object is tied to the lifetime of the
/// ServiceConfig object.
ParsedConfig* GetGlobalParsedConfig(size_t index) {
ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) {
GPR_DEBUG_ASSERT(index < parsed_global_configs_.size());
return parsed_global_configs_[index].get();
}
@ -148,47 +84,37 @@ class ServiceConfig : public RefCounted<ServiceConfig> {
/// Retrieves the vector of parsed configs for the method identified
/// by \a path. The lifetime of the returned vector and contained objects
/// is tied to the lifetime of the ServiceConfig object.
const ParsedConfigVector* GetMethodParsedConfigVector(
const ServiceConfigParser::ParsedConfigVector* GetMethodParsedConfigVector(
const grpc_slice& path) const;
/// Globally register a service config parser. On successful registration, it
/// returns the index at which the parser was registered. On failure, -1 is
/// returned. Each new service config update will go through all the
/// registered parser. Each parser is responsible for reading the service
/// config json and returning a parsed config. This parsed config can later be
/// retrieved using the same index that was returned at registration time.
static size_t RegisterParser(std::unique_ptr<Parser> parser);
static void Init();
static void Shutdown();
private:
// Helper functions to parse the service config
grpc_error* ParseGlobalParams();
// Helper functions for parsing the method configs.
grpc_error* ParsePerMethodParams();
grpc_error* ParseJsonMethodConfig(const Json& json);
// Returns a path string for the JSON name object specified by json.
// Sets *error on error.
static std::string ParseJsonMethodName(const Json& json, grpc_error** error);
grpc_error* ParseJsonMethodConfig(const Json& json);
std::string json_string_;
Json json_;
absl::InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers>
absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfig>,
ServiceConfigParser::kNumPreallocatedParsers>
parsed_global_configs_;
// A map from the method name to the parsed config vector. Note that we are
// using a raw pointer and not a unique pointer so that we can use the same
// vector for multiple names.
std::unordered_map<grpc_slice, const ParsedConfigVector*, SliceHash>
std::unordered_map<grpc_slice, const ServiceConfigParser::ParsedConfigVector*,
SliceHash>
parsed_method_configs_map_;
// Default method config.
const ParsedConfigVector* default_method_config_vector_ = nullptr;
const ServiceConfigParser::ParsedConfigVector* default_method_config_vector_ =
nullptr;
// Storage for all the vectors that are being used in
// parsed_method_configs_table_.
absl::InlinedVector<std::unique_ptr<ParsedConfigVector>, 32>
absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfigVector>,
32>
parsed_method_config_vectors_storage_;
};

@ -0,0 +1,68 @@
//
// Copyright 2016 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
namespace grpc_core {
/// When a service config is applied to a call in the client_channel_filter,
/// we create an instance of this object on the arena. A pointer to this
/// object is also stored in the call_context, so that future filters can
/// easily access method and global parameters for the call.
class ServiceConfigCallData {
public:
ServiceConfigCallData(
RefCountedPtr<ServiceConfig> service_config,
const ServiceConfigParser::ParsedConfigVector* method_configs,
grpc_call_context_element* call_context)
: service_config_(std::move(service_config)),
method_configs_(method_configs) {
call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
}
ServiceConfig* service_config() { return service_config_.get(); }
ServiceConfigParser::ParsedConfig* GetMethodParsedConfig(size_t index) const {
return method_configs_ != nullptr ? (*method_configs_)[index].get()
: nullptr;
}
ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) const {
return service_config_->GetGlobalParsedConfig(index);
}
private:
static void Destroy(void* ptr) {
ServiceConfigCallData* self = static_cast<ServiceConfigCallData*>(ptr);
self->~ServiceConfigCallData();
}
RefCountedPtr<ServiceConfig> service_config_;
const ServiceConfigParser::ParsedConfigVector* method_configs_ = nullptr;
};
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_CALL_DATA_H */

@ -0,0 +1,87 @@
//
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include <grpc/support/log.h>
namespace grpc_core {
namespace {
typedef absl::InlinedVector<std::unique_ptr<ServiceConfigParser::Parser>,
ServiceConfigParser::kNumPreallocatedParsers>
ServiceConfigParserList;
ServiceConfigParserList* g_registered_parsers;
} // namespace
void ServiceConfigParser::Init() {
GPR_ASSERT(g_registered_parsers == nullptr);
g_registered_parsers = new ServiceConfigParserList();
}
void ServiceConfigParser::Shutdown() {
delete g_registered_parsers;
g_registered_parsers = nullptr;
}
size_t ServiceConfigParser::RegisterParser(std::unique_ptr<Parser> parser) {
g_registered_parsers->push_back(std::move(parser));
return g_registered_parsers->size() - 1;
}
ServiceConfigParser::ParsedConfigVector
ServiceConfigParser::ParseGlobalParameters(const Json& json,
grpc_error** error) {
ParsedConfigVector parsed_global_configs;
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < g_registered_parsers->size(); i++) {
grpc_error* parser_error = GRPC_ERROR_NONE;
auto parsed_config =
(*g_registered_parsers)[i]->ParseGlobalParams(json, &parser_error);
if (parser_error != GRPC_ERROR_NONE) {
error_list.push_back(parser_error);
}
parsed_global_configs.push_back(std::move(parsed_config));
}
if (!error_list.empty()) {
*error = GRPC_ERROR_CREATE_FROM_VECTOR("Global Params", &error_list);
}
return parsed_global_configs;
}
ServiceConfigParser::ParsedConfigVector
ServiceConfigParser::ParsePerMethodParameters(const Json& json,
grpc_error** error) {
ParsedConfigVector parsed_method_configs;
std::vector<grpc_error*> error_list;
for (size_t i = 0; i < g_registered_parsers->size(); i++) {
grpc_error* parser_error = GRPC_ERROR_NONE;
auto parsed_config =
(*g_registered_parsers)[i]->ParsePerMethodParams(json, &parser_error);
if (parser_error != GRPC_ERROR_NONE) {
error_list.push_back(parser_error);
}
parsed_method_configs.push_back(std::move(parsed_config));
}
if (!error_list.empty()) {
*error = GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list);
}
return parsed_method_configs;
}
} // namespace grpc_core

@ -0,0 +1,89 @@
//
// Copyright 2016 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H
#include <grpc/support/port_platform.h>
#include <memory>
#include "absl/container/inlined_vector.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/json/json.h"
namespace grpc_core {
// Service config parser registry.
// See service_config.h for more information.
class ServiceConfigParser {
public:
/// This is the base class that all service config parsers MUST use to store
/// parsed service config data.
class ParsedConfig {
public:
virtual ~ParsedConfig() = default;
};
/// This is the base class that all service config parsers should derive from.
class Parser {
public:
virtual ~Parser() = default;
virtual std::unique_ptr<ParsedConfig> ParseGlobalParams(
const Json& /* json */, grpc_error** error) {
// Avoid unused parameter warning on debug-only parameter
(void)error;
GPR_DEBUG_ASSERT(error != nullptr);
return nullptr;
}
virtual std::unique_ptr<ParsedConfig> ParsePerMethodParams(
const Json& /* json */, grpc_error** error) {
// Avoid unused parameter warning on debug-only parameter
(void)error;
GPR_DEBUG_ASSERT(error != nullptr);
return nullptr;
}
};
static constexpr int kNumPreallocatedParsers = 4;
typedef absl::InlinedVector<std::unique_ptr<ParsedConfig>,
kNumPreallocatedParsers>
ParsedConfigVector;
static void Init();
static void Shutdown();
/// Globally register a service config parser. On successful registration, it
/// returns the index at which the parser was registered. On failure, -1 is
/// returned. Each new service config update will go through all the
/// registered parser. Each parser is responsible for reading the service
/// config json and returning a parsed config. This parsed config can later be
/// retrieved using the same index that was returned at registration time.
static size_t RegisterParser(std::unique_ptr<Parser> parser);
static ParsedConfigVector ParseGlobalParameters(const Json& json,
grpc_error** error);
static ParsedConfigVector ParsePerMethodParameters(const Json& json,
grpc_error** error);
};
} // namespace grpc_core
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVICE_CONFIG_PARSER_H */

@ -23,8 +23,6 @@
#include <errno.h>
#include <stdlib.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include <grpc/support/string_util.h>
@ -38,36 +36,47 @@ namespace grpc_core {
namespace {
std::string BootstrapString(const XdsBootstrap& bootstrap) {
std::vector<std::string> parts;
UniquePtr<char> BootstrapString(const XdsBootstrap& bootstrap) {
gpr_strvec v;
gpr_strvec_init(&v);
char* tmp;
if (bootstrap.node() != nullptr) {
parts.push_back(absl::StrFormat(
"node={\n"
" id=\"%s\",\n"
" cluster=\"%s\",\n"
" locality={\n"
" region=\"%s\",\n"
" zone=\"%s\",\n"
" subzone=\"%s\"\n"
" },\n"
" metadata=%s,\n"
"},\n",
bootstrap.node()->id, bootstrap.node()->cluster,
bootstrap.node()->locality_region, bootstrap.node()->locality_zone,
bootstrap.node()->locality_subzone, bootstrap.node()->metadata.Dump()));
gpr_asprintf(&tmp,
"node={\n"
" id=\"%s\",\n"
" cluster=\"%s\",\n"
" locality={\n"
" region=\"%s\",\n"
" zone=\"%s\",\n"
" subzone=\"%s\"\n"
" },\n"
" metadata=%s,\n"
"},\n",
bootstrap.node()->id.c_str(),
bootstrap.node()->cluster.c_str(),
bootstrap.node()->locality_region.c_str(),
bootstrap.node()->locality_zone.c_str(),
bootstrap.node()->locality_subzone.c_str(),
bootstrap.node()->metadata.Dump().c_str());
gpr_strvec_add(&v, tmp);
}
parts.push_back(
absl::StrFormat("servers=[\n"
" {\n"
" uri=\"%s\",\n"
" creds=[\n",
bootstrap.server().server_uri));
for (const auto& creds : bootstrap.server().channel_creds) {
parts.push_back(absl::StrFormat(" {type=\"%s\", config=%s},\n",
creds.type, creds.config.Dump()));
gpr_asprintf(&tmp,
"servers=[\n"
" {\n"
" uri=\"%s\",\n"
" creds=[\n",
bootstrap.server().server_uri.c_str());
gpr_strvec_add(&v, tmp);
for (size_t i = 0; i < bootstrap.server().channel_creds.size(); ++i) {
const auto& creds = bootstrap.server().channel_creds[i];
gpr_asprintf(&tmp, " {type=\"%s\", config=%s},\n", creds.type.c_str(),
creds.config.Dump().c_str());
gpr_strvec_add(&v, tmp);
}
parts.push_back(" ]\n }\n]");
return absl::StrJoin(parts, "");
gpr_strvec_add(&v, gpr_strdup(" ]\n }\n]"));
UniquePtr<char> result(gpr_strvec_flatten(&v, nullptr));
gpr_strvec_destroy(&v);
return result;
}
} // namespace
@ -112,7 +121,7 @@ std::unique_ptr<XdsBootstrap> XdsBootstrap::ReadFromFile(XdsClient* client,
if (*error == GRPC_ERROR_NONE && GRPC_TRACE_FLAG_ENABLED(*tracer)) {
gpr_log(GPR_INFO,
"[xds_client %p] Bootstrap config for creating xds client:\n%s",
client, BootstrapString(*result).c_str());
client, BootstrapString(*result).get());
}
return result;
}

@ -2043,7 +2043,7 @@ namespace {
std::string CreateServiceConfigActionCluster(const std::string& cluster_name) {
return absl::StrFormat(
" \"cds:%s\":{\n"
" \"child_policy\":[ {\n"
" \"childPolicy\":[ {\n"
" \"cds_experimental\":{\n"
" \"cluster\": \"%s\"\n"
" }\n"
@ -2073,7 +2073,7 @@ std::string CreateServiceConfigActionWeightedCluster(
std::vector<std::string> config_parts;
config_parts.push_back(
absl::StrFormat(" \"weighted:%s\":{\n"
" \"child_policy\":[ {\n"
" \"childPolicy\":[ {\n"
" \"weighted_target_experimental\":{\n"
" \"targets\":{\n",
name));

@ -17,19 +17,11 @@
#include <grpc/support/port_platform.h>
#include <stdint.h>
#include <string.h>
#include <string>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <stdint.h>
#include <string.h>
#include "src/core/ext/filters/http/client/http_client_filter.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/gprpp/manual_constructor.h"
@ -528,36 +520,50 @@ static size_t max_payload_size_from_args(const grpc_channel_args* args) {
static grpc_core::ManagedMemorySlice user_agent_from_args(
const grpc_channel_args* args, const char* transport_name) {
std::vector<std::string> user_agent_fields;
gpr_strvec v;
size_t i;
int is_first = 1;
char* tmp;
for (size_t i = 0; args && i < args->num_args; i++) {
gpr_strvec_init(&v);
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_PRIMARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_PRIMARY_USER_AGENT_STRING);
} else {
user_agent_fields.push_back(args->args[i].value.string);
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
}
}
}
user_agent_fields.push_back(
absl::StrFormat("grpc-c/%s (%s; %s)", grpc_version_string(),
GPR_PLATFORM_STRING, transport_name));
gpr_asprintf(&tmp, "%sgrpc-c/%s (%s; %s)", is_first ? "" : " ",
grpc_version_string(), GPR_PLATFORM_STRING, transport_name);
is_first = 0;
gpr_strvec_add(&v, tmp);
for (size_t i = 0; args && i < args->num_args; i++) {
for (i = 0; args && i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_SECONDARY_USER_AGENT_STRING)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "Channel argument '%s' should be a string",
GRPC_ARG_SECONDARY_USER_AGENT_STRING);
} else {
user_agent_fields.push_back(args->args[i].value.string);
if (!is_first) gpr_strvec_add(&v, gpr_strdup(" "));
is_first = 0;
gpr_strvec_add(&v, gpr_strdup(args->args[i].value.string));
}
}
}
std::string user_agent_string = absl::StrJoin(user_agent_fields, " ");
return grpc_core::ManagedMemorySlice(user_agent_string.c_str());
tmp = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
grpc_core::ManagedMemorySlice result(tmp);
gpr_free(tmp);
return result;
}
/* Constructor for channel_data */

@ -27,6 +27,7 @@
#include <grpc/support/string_util.h>
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/service_config_call_data.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/gpr/string.h"
@ -44,7 +45,7 @@ namespace {
size_t g_message_size_parser_index;
} // namespace
std::unique_ptr<ServiceConfig::ParsedConfig>
std::unique_ptr<ServiceConfigParser::ParsedConfig>
MessageSizeParser::ParsePerMethodParams(const Json& json, grpc_error** error) {
GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE);
std::vector<grpc_error*> error_list;
@ -91,8 +92,8 @@ MessageSizeParser::ParsePerMethodParams(const Json& json, grpc_error** error) {
}
void MessageSizeParser::Register() {
g_message_size_parser_index =
ServiceConfig::RegisterParser(absl::make_unique<MessageSizeParser>());
g_message_size_parser_index = ServiceConfigParser::RegisterParser(
absl::make_unique<MessageSizeParser>());
}
size_t MessageSizeParser::ParserIndex() { return g_message_size_parser_index; }
@ -118,9 +119,9 @@ struct call_data {
// apply the max request size to the send limit and the max response
// size to the receive limit.
const grpc_core::MessageSizeParsedConfig* limits = nullptr;
grpc_core::ServiceConfig::CallData* svc_cfg_call_data = nullptr;
grpc_core::ServiceConfigCallData* svc_cfg_call_data = nullptr;
if (args.context != nullptr) {
svc_cfg_call_data = static_cast<grpc_core::ServiceConfig::CallData*>(
svc_cfg_call_data = static_cast<grpc_core::ServiceConfigCallData*>(
args.context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
}
if (svc_cfg_call_data != nullptr) {

@ -19,14 +19,14 @@
#include <grpc/support/port_platform.h>
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/lib/channel/channel_stack.h"
extern const grpc_channel_filter grpc_message_size_filter;
namespace grpc_core {
class MessageSizeParsedConfig : public ServiceConfig::ParsedConfig {
class MessageSizeParsedConfig : public ServiceConfigParser::ParsedConfig {
public:
struct message_size_limits {
int max_send_size;
@ -44,9 +44,9 @@ class MessageSizeParsedConfig : public ServiceConfig::ParsedConfig {
message_size_limits limits_;
};
class MessageSizeParser : public ServiceConfig::Parser {
class MessageSizeParser : public ServiceConfigParser::Parser {
public:
std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
const Json& json, grpc_error** error) override;
static void Register();

@ -1356,8 +1356,10 @@ static void perform_stream_op_locked(void* stream_op,
s->context = op->payload->context;
s->traced = op->is_traced;
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p",
grpc_transport_stream_op_batch_string(op).c_str(), op->on_complete);
char* str = grpc_transport_stream_op_batch_string(op);
gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str,
op->on_complete);
gpr_free(str);
if (op->send_initial_metadata) {
log_metadata(op_payload->send_initial_metadata.send_initial_metadata,
s->id, t->is_client, true);
@ -1652,8 +1654,9 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
}
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s,
grpc_transport_stream_op_batch_string(op).c_str());
char* str = grpc_transport_stream_op_batch_string(op);
gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s, str);
gpr_free(str);
}
GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
@ -1842,8 +1845,9 @@ static void perform_transport_op_locked(void* stream_op,
static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(gt);
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) {
gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t,
grpc_transport_op_string(op).c_str());
char* msg = grpc_transport_op_string(op);
gpr_log(GPR_INFO, "perform_transport_op[t=%p]: %s", t, msg);
gpr_free(msg);
}
op->handler_private.extra_arg = gt;
GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op");

@ -812,6 +812,24 @@ void op_state_machine_locked(inproc_stream* s, grpc_error* error) {
"op_state_machine %p has trailing md but not yet waiting for it", s);
}
}
if (!s->t->is_client && s->trailing_md_sent &&
(s->recv_trailing_md_op != nullptr)) {
// In this case, we don't care to receive the write-close from the client
// because we have already sent status and the RPC is over as far as we
// are concerned.
INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling trailing-md-ready %p",
s, new_err);
grpc_core::ExecCtx::Run(
DEBUG_LOCATION,
s->recv_trailing_md_op->payload->recv_trailing_metadata
.recv_trailing_metadata_ready,
GRPC_ERROR_REF(new_err));
complete_if_batch_end_locked(
s, new_err, s->recv_trailing_md_op,
"op_state_machine scheduling recv-trailing-md-on-complete");
s->trailing_md_recvd = true;
s->recv_trailing_md_op = nullptr;
}
if (s->trailing_md_recvd && s->recv_message_op) {
// No further message will come on this stream, so finish off the
// recv_message_op

@ -130,23 +130,24 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1
&google_protobuf_FieldOptions_msginit,
};
static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[10] = {
{1, UPB_SIZE(32, 32), 5, 0, 9, 1},
{2, UPB_SIZE(40, 48), 6, 0, 9, 1},
static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
{1, UPB_SIZE(36, 40), 6, 0, 9, 1},
{2, UPB_SIZE(44, 56), 7, 0, 9, 1},
{3, UPB_SIZE(24, 24), 3, 0, 5, 1},
{4, UPB_SIZE(8, 8), 1, 0, 14, 1},
{5, UPB_SIZE(16, 16), 2, 0, 14, 1},
{6, UPB_SIZE(48, 64), 7, 0, 9, 1},
{7, UPB_SIZE(56, 80), 8, 0, 9, 1},
{8, UPB_SIZE(72, 112), 10, 0, 11, 1},
{6, UPB_SIZE(52, 72), 8, 0, 9, 1},
{7, UPB_SIZE(60, 88), 9, 0, 9, 1},
{8, UPB_SIZE(76, 120), 11, 0, 11, 1},
{9, UPB_SIZE(28, 28), 4, 0, 5, 1},
{10, UPB_SIZE(64, 96), 9, 0, 9, 1},
{10, UPB_SIZE(68, 104), 10, 0, 9, 1},
{17, UPB_SIZE(32, 32), 5, 0, 8, 1},
};
const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
&google_protobuf_FieldDescriptorProto_submsgs[0],
&google_protobuf_FieldDescriptorProto__fields[0],
UPB_SIZE(80, 128), 10, false,
UPB_SIZE(80, 128), 11, false,
};
static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {

@ -598,34 +598,36 @@ UPB_INLINE char *google_protobuf_FieldDescriptorProto_serialize(const google_pro
return upb_encode(msg, &google_protobuf_FieldDescriptorProto_msginit, arena, len);
}
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 6); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 40)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 56)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 3); }
UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(24, 24)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 1); }
UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(8, 8)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 2); }
UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 7); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(72, 112)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 8); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 72)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 88)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 11); }
UPB_INLINE const google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_options(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, const google_protobuf_FieldOptions*, UPB_SIZE(76, 120)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 4); }
UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 9); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 10); }
UPB_INLINE upb_strview google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 104)); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return _upb_has_field(msg, 5); }
UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(32, 32)); }
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
_upb_sethas(msg, 5);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(32, 32)) = value;
_upb_sethas(msg, 6);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(36, 40)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
_upb_sethas(msg, 6);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(40, 48)) = value;
_upb_sethas(msg, 7);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(44, 56)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
_upb_sethas(msg, 3);
@ -640,16 +642,16 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_Fi
UPB_FIELD_AT(msg, int32_t, UPB_SIZE(16, 16)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
_upb_sethas(msg, 7);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(48, 64)) = value;
_upb_sethas(msg, 8);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(52, 72)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
_upb_sethas(msg, 8);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(56, 80)) = value;
_upb_sethas(msg, 9);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(60, 88)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
_upb_sethas(msg, 10);
UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(72, 112)) = value;
_upb_sethas(msg, 11);
UPB_FIELD_AT(msg, google_protobuf_FieldOptions*, UPB_SIZE(76, 120)) = value;
}
UPB_INLINE struct google_protobuf_FieldOptions* google_protobuf_FieldDescriptorProto_mutable_options(google_protobuf_FieldDescriptorProto *msg, upb_arena *arena) {
struct google_protobuf_FieldOptions* sub = (struct google_protobuf_FieldOptions*)google_protobuf_FieldDescriptorProto_options(msg);
@ -665,8 +667,12 @@ UPB_INLINE void google_protobuf_FieldDescriptorProto_set_oneof_index(google_prot
UPB_FIELD_AT(msg, int32_t, UPB_SIZE(28, 28)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_strview value) {
_upb_sethas(msg, 9);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(64, 96)) = value;
_upb_sethas(msg, 10);
UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(68, 104)) = value;
}
UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
_upb_sethas(msg, 5);
UPB_FIELD_AT(msg, bool, UPB_SIZE(32, 32)) = value;
}
/* google.protobuf.OneofDescriptorProto */

@ -21,11 +21,6 @@
#include <limits.h>
#include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/grpc.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/impl/codegen/log.h>
@ -341,28 +336,32 @@ grpc_arg grpc_channel_arg_pointer_create(
return arg;
}
std::string grpc_channel_args_string(const grpc_channel_args* args) {
char* grpc_channel_args_string(const grpc_channel_args* args) {
if (args == nullptr) return nullptr;
std::vector<std::string> arg_strings;
gpr_strvec v;
gpr_strvec_init(&v);
for (size_t i = 0; i < args->num_args; ++i) {
const grpc_arg& arg = args->args[i];
std::string arg_string;
char* s;
switch (arg.type) {
case GRPC_ARG_INTEGER:
arg_string = absl::StrFormat("%s=%d", arg.key, arg.value.integer);
gpr_asprintf(&s, "%s=%d", arg.key, arg.value.integer);
break;
case GRPC_ARG_STRING:
arg_string = absl::StrFormat("%s=%s", arg.key, arg.value.string);
gpr_asprintf(&s, "%s=%s", arg.key, arg.value.string);
break;
case GRPC_ARG_POINTER:
arg_string = absl::StrFormat("%s=%p", arg.key, arg.value.pointer.p);
gpr_asprintf(&s, "%s=%p", arg.key, arg.value.pointer.p);
break;
default:
arg_string = "arg with unknown type";
gpr_asprintf(&s, "arg with unknown type");
}
arg_strings.push_back(arg_string);
gpr_strvec_add(&v, s);
}
return absl::StrJoin(arg_strings, ", ");
char* result =
gpr_strjoin_sep(const_cast<const char**>(v.strs), v.count, ", ", nullptr);
gpr_strvec_destroy(&v);
return result;
}
namespace {

@ -21,8 +21,6 @@
#include <grpc/support/port_platform.h>
#include <string>
#include <grpc/grpc.h>
#include "src/core/lib/surface/channel_stack_type.h"
@ -118,7 +116,7 @@ grpc_arg grpc_channel_arg_pointer_create(char* name, void* value,
// Returns a string representing channel args in human-readable form.
// Callers takes ownership of result.
std::string grpc_channel_args_string(const grpc_channel_args* args);
char* grpc_channel_args_string(const grpc_channel_args* args);
// Takes ownership of the old_args
typedef grpc_channel_args* (*grpc_channel_args_client_channel_creation_mutator)(

@ -35,7 +35,7 @@ typedef enum {
/// Reserved for traffic_class_context.
GRPC_CONTEXT_TRAFFIC,
/// Holds a pointer to ServiceConfig::CallData associated with this call.
/// Holds a pointer to ServiceConfigCallData associated with this call.
GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA,
GRPC_CONTEXT_COUNT

@ -20,8 +20,6 @@
#include <string.h>
#include "absl/strings/str_format.h"
#include <grpc/impl/codegen/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
@ -39,16 +37,19 @@ TraceFlag grpc_handshaker_trace(false, "handshaker");
namespace {
std::string HandshakerArgsString(HandshakerArgs* args) {
char* HandshakerArgsString(HandshakerArgs* args) {
char* args_str = grpc_channel_args_string(args->args);
size_t num_args = args->args != nullptr ? args->args->num_args : 0;
size_t read_buffer_length =
args->read_buffer != nullptr ? args->read_buffer->length : 0;
return absl::StrFormat(
"{endpoint=%p, args=%p {size=%" PRIuPTR
": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}",
args->endpoint, args->args, num_args,
grpc_channel_args_string(args->args), args->read_buffer,
read_buffer_length, args->exit_early);
char* str;
gpr_asprintf(&str,
"{endpoint=%p, args=%p {size=%" PRIuPTR
": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}",
args->endpoint, args->args, num_args, args_str,
args->read_buffer, read_buffer_length, args->exit_early);
gpr_free(args_str);
return str;
}
} // namespace
@ -126,11 +127,12 @@ void HandshakeManager::Shutdown(grpc_error* why) {
// Returns true if we've scheduled the on_handshake_done callback.
bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) {
if (GRPC_TRACE_FLAG_ENABLED(grpc_handshaker_trace)) {
char* args_str = HandshakerArgsString(&args_);
gpr_log(GPR_INFO,
"handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR
", args=%s",
this, grpc_error_string(error), is_shutdown_, index_,
HandshakerArgsString(&args_).c_str());
this, grpc_error_string(error), is_shutdown_, index_, args_str);
gpr_free(args_str);
}
GPR_ASSERT(index_ <= handshakers_.size());
// If we got an error or we've been shut down or we're exiting early or

@ -23,11 +23,6 @@
#include <inttypes.h>
#include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
@ -145,28 +140,39 @@ double grpc_stats_histo_percentile(const grpc_stats_data* stats,
static_cast<double>(count) * percentile / 100.0);
}
std::string grpc_stats_data_as_json(const grpc_stats_data* data) {
std::vector<std::string> parts;
parts.push_back("{");
char* grpc_stats_data_as_json(const grpc_stats_data* data) {
gpr_strvec v;
char* tmp;
bool is_first = true;
gpr_strvec_init(&v);
gpr_strvec_add(&v, gpr_strdup("{"));
for (size_t i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
parts.push_back(absl::StrFormat(
"\"%s\": %" PRIdPTR, grpc_stats_counter_name[i], data->counters[i]));
gpr_asprintf(&tmp, "%s\"%s\": %" PRIdPTR, is_first ? "" : ", ",
grpc_stats_counter_name[i], data->counters[i]);
gpr_strvec_add(&v, tmp);
is_first = false;
}
for (size_t i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
parts.push_back(absl::StrFormat("\"%s\": [", grpc_stats_histogram_name[i]));
gpr_asprintf(&tmp, "%s\"%s\": [", is_first ? "" : ", ",
grpc_stats_histogram_name[i]);
gpr_strvec_add(&v, tmp);
for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
parts.push_back(
absl::StrFormat("%s%" PRIdPTR, j == 0 ? "" : ",",
data->histograms[grpc_stats_histo_start[i] + j]));
gpr_asprintf(&tmp, "%s%" PRIdPTR, j == 0 ? "" : ",",
data->histograms[grpc_stats_histo_start[i] + j]);
gpr_strvec_add(&v, tmp);
}
parts.push_back(
absl::StrFormat("], \"%s_bkt\": [", grpc_stats_histogram_name[i]));
gpr_asprintf(&tmp, "], \"%s_bkt\": [", grpc_stats_histogram_name[i]);
gpr_strvec_add(&v, tmp);
for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
parts.push_back(absl::StrFormat(
"%s%d", j == 0 ? "" : ",", grpc_stats_histo_bucket_boundaries[i][j]));
gpr_asprintf(&tmp, "%s%d", j == 0 ? "" : ",",
grpc_stats_histo_bucket_boundaries[i][j]);
gpr_strvec_add(&v, tmp);
}
parts.push_back("]");
gpr_strvec_add(&v, gpr_strdup("]"));
is_first = false;
}
parts.push_back("}");
return absl::StrJoin(parts, "");
gpr_strvec_add(&v, gpr_strdup("}"));
tmp = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
return tmp;
}

@ -58,7 +58,7 @@ void grpc_stats_collect(grpc_stats_data* output);
// c = b-a
void grpc_stats_diff(const grpc_stats_data* b, const grpc_stats_data* a,
grpc_stats_data* c);
std::string grpc_stats_data_as_json(const grpc_stats_data* data);
char* grpc_stats_data_as_json(const grpc_stats_data* data);
int grpc_stats_histo_find_bucket_slow(int value, const int* table,
int table_size);
double grpc_stats_histo_percentile(const grpc_stats_data* data,

@ -266,6 +266,29 @@ char* gpr_strjoin_sep(const char** strs, size_t nstrs, const char* sep,
return out;
}
void gpr_strvec_init(gpr_strvec* sv) { memset(sv, 0, sizeof(*sv)); }
void gpr_strvec_destroy(gpr_strvec* sv) {
size_t i;
for (i = 0; i < sv->count; i++) {
gpr_free(sv->strs[i]);
}
gpr_free(sv->strs);
}
void gpr_strvec_add(gpr_strvec* sv, char* str) {
if (sv->count == sv->capacity) {
sv->capacity = GPR_MAX(sv->capacity + 8, sv->capacity * 2);
sv->strs = static_cast<char**>(
gpr_realloc(sv->strs, sizeof(char*) * sv->capacity));
}
sv->strs[sv->count++] = str;
}
char* gpr_strvec_flatten(gpr_strvec* sv, size_t* final_length) {
return gpr_strjoin((const char**)sv->strs, sv->count, final_length);
}
int gpr_strincmp(const char* a, const char* b, size_t n) {
int ca, cb;
do {

@ -96,6 +96,22 @@ void gpr_string_split(const char* input, const char* sep, char*** strs,
0, 3, 6 or 9 fractional digits. */
char* gpr_format_timespec(gpr_timespec);
/* A vector of strings... for building up a final string one piece at a time */
typedef struct {
char** strs;
size_t count;
size_t capacity;
} gpr_strvec;
/* Initialize/destroy */
void gpr_strvec_init(gpr_strvec* strs);
void gpr_strvec_destroy(gpr_strvec* strs);
/* Add a string to a strvec, takes ownership of the string */
void gpr_strvec_add(gpr_strvec* strs, char* add);
/* Return a joined string with all added substrings, optionally setting
total_length as per gpr_strjoin */
char* gpr_strvec_flatten(gpr_strvec* strs, size_t* total_length);
/** Case insensitive string comparison... return <0 if lower(a)<lower(b), ==0 if
lower(a)==lower(b), >0 if lower(a)>lower(b) */
int gpr_stricmp(const char* a, const char* b);

@ -24,80 +24,99 @@
#include <stdio.h>
#include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/slice.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
static void fill_common_header(const grpc_httpcli_request* request,
bool connection_close,
std::vector<std::string>* buf) {
buf->push_back(request->http.path);
buf->push_back(" HTTP/1.0\r\n");
gpr_strvec* buf, bool connection_close) {
size_t i;
gpr_strvec_add(buf, gpr_strdup(request->http.path));
gpr_strvec_add(buf, gpr_strdup(" HTTP/1.0\r\n"));
/* just in case some crazy server really expects HTTP/1.1 */
buf->push_back("Host: ");
buf->push_back(request->host);
buf->push_back("\r\n");
if (connection_close) buf->push_back("Connection: close\r\n");
buf->push_back("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n");
gpr_strvec_add(buf, gpr_strdup("Host: "));
gpr_strvec_add(buf, gpr_strdup(request->host));
gpr_strvec_add(buf, gpr_strdup("\r\n"));
if (connection_close)
gpr_strvec_add(buf, gpr_strdup("Connection: close\r\n"));
gpr_strvec_add(buf,
gpr_strdup("User-Agent: " GRPC_HTTPCLI_USER_AGENT "\r\n"));
/* user supplied headers */
for (size_t i = 0; i < request->http.hdr_count; i++) {
buf->push_back(request->http.hdrs[i].key);
buf->push_back(": ");
buf->push_back(request->http.hdrs[i].value);
buf->push_back("\r\n");
for (i = 0; i < request->http.hdr_count; i++) {
gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].key));
gpr_strvec_add(buf, gpr_strdup(": "));
gpr_strvec_add(buf, gpr_strdup(request->http.hdrs[i].value));
gpr_strvec_add(buf, gpr_strdup("\r\n"));
}
}
grpc_slice grpc_httpcli_format_get_request(
const grpc_httpcli_request* request) {
std::vector<std::string> out;
out.push_back("GET ");
fill_common_header(request, true, &out);
out.push_back("\r\n");
std::string req = absl::StrJoin(out, "");
return grpc_slice_from_copied_buffer(req.data(), req.size());
gpr_strvec out;
char* flat;
size_t flat_len;
gpr_strvec_init(&out);
gpr_strvec_add(&out, gpr_strdup("GET "));
fill_common_header(request, &out, true);
gpr_strvec_add(&out, gpr_strdup("\r\n"));
flat = gpr_strvec_flatten(&out, &flat_len);
gpr_strvec_destroy(&out);
return grpc_slice_new(flat, flat_len, gpr_free);
}
grpc_slice grpc_httpcli_format_post_request(const grpc_httpcli_request* request,
const char* body_bytes,
size_t body_size) {
std::vector<std::string> out;
out.push_back("POST ");
fill_common_header(request, true, &out);
if (body_bytes != nullptr) {
bool has_content_type = false;
for (size_t i = 0; i < request->http.hdr_count; i++) {
gpr_strvec out;
char* tmp;
size_t out_len;
size_t i;
gpr_strvec_init(&out);
gpr_strvec_add(&out, gpr_strdup("POST "));
fill_common_header(request, &out, true);
if (body_bytes) {
uint8_t has_content_type = 0;
for (i = 0; i < request->http.hdr_count; i++) {
if (strcmp(request->http.hdrs[i].key, "Content-Type") == 0) {
has_content_type = true;
has_content_type = 1;
break;
}
}
if (!has_content_type) {
out.push_back("Content-Type: text/plain\r\n");
gpr_strvec_add(&out, gpr_strdup("Content-Type: text/plain\r\n"));
}
out.push_back(absl::StrFormat("Content-Length: %lu\r\n",
static_cast<unsigned long>(body_size)));
gpr_asprintf(&tmp, "Content-Length: %lu\r\n",
static_cast<unsigned long>(body_size));
gpr_strvec_add(&out, tmp);
}
out.push_back("\r\n");
std::string req = absl::StrJoin(out, "");
if (body_bytes != nullptr) {
absl::StrAppend(&req, absl::string_view(body_bytes, body_size));
gpr_strvec_add(&out, gpr_strdup("\r\n"));
tmp = gpr_strvec_flatten(&out, &out_len);
gpr_strvec_destroy(&out);
if (body_bytes) {
tmp = static_cast<char*>(gpr_realloc(tmp, out_len + body_size));
memcpy(tmp + out_len, body_bytes, body_size);
out_len += body_size;
}
return grpc_slice_from_copied_buffer(req.data(), req.size());
return grpc_slice_new(tmp, out_len, gpr_free);
}
grpc_slice grpc_httpcli_format_connect_request(
const grpc_httpcli_request* request) {
std::vector<std::string> out;
out.push_back("CONNECT ");
fill_common_header(request, false, &out);
out.push_back("\r\n");
std::string req = absl::StrJoin(out, "");
return grpc_slice_from_copied_buffer(req.data(), req.size());
gpr_strvec out;
gpr_strvec_init(&out);
gpr_strvec_add(&out, gpr_strdup("CONNECT "));
fill_common_header(request, &out, false);
gpr_strvec_add(&out, gpr_strdup("\r\n"));
size_t flat_len;
char* flat = gpr_strvec_flatten(&out, &flat_len);
gpr_strvec_destroy(&out);
return grpc_slice_new(flat, flat_len, gpr_free);
}

@ -38,11 +38,6 @@
#include <sys/socket.h>
#include <unistd.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/cpu.h>
#include <grpc/support/string_util.h>
@ -1069,23 +1064,30 @@ static grpc_error* pollset_kick(grpc_pollset* pollset,
GRPC_STATS_INC_POLLSET_KICK();
grpc_error* ret_err = GRPC_ERROR_NONE;
if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) {
std::vector<std::string> log;
log.push_back(absl::StrFormat(
"PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset, specific_worker,
(void*)gpr_tls_get(&g_current_thread_pollset),
(void*)gpr_tls_get(&g_current_thread_worker), pollset->root_worker));
gpr_strvec log;
gpr_strvec_init(&log);
char* tmp;
gpr_asprintf(&tmp, "PS:%p KICK:%p curps=%p curworker=%p root=%p", pollset,
specific_worker, (void*)gpr_tls_get(&g_current_thread_pollset),
(void*)gpr_tls_get(&g_current_thread_worker),
pollset->root_worker);
gpr_strvec_add(&log, tmp);
if (pollset->root_worker != nullptr) {
log.push_back(absl::StrFormat(
" {kick_state=%s next=%p {kick_state=%s}}",
kick_state_string(pollset->root_worker->state),
pollset->root_worker->next,
kick_state_string(pollset->root_worker->next->state)));
gpr_asprintf(&tmp, " {kick_state=%s next=%p {kick_state=%s}}",
kick_state_string(pollset->root_worker->state),
pollset->root_worker->next,
kick_state_string(pollset->root_worker->next->state));
gpr_strvec_add(&log, tmp);
}
if (specific_worker != nullptr) {
log.push_back(absl::StrFormat(" worker_kick_state=%s",
kick_state_string(specific_worker->state)));
gpr_asprintf(&tmp, " worker_kick_state=%s",
kick_state_string(specific_worker->state));
gpr_strvec_add(&log, tmp);
}
gpr_log(GPR_DEBUG, "%s", absl::StrJoin(log, "").c_str());
tmp = gpr_strvec_flatten(&log, nullptr);
gpr_strvec_destroy(&log);
gpr_log(GPR_DEBUG, "%s", tmp);
gpr_free(tmp);
}
if (specific_worker == nullptr) {

@ -24,7 +24,6 @@
#include <string.h>
#include "absl/container/inlined_vector.h"
#include "absl/strings/str_join.h"
#include <grpc/grpc_security.h>
#include <grpc/impl/codegen/slice.h>
@ -524,10 +523,12 @@ namespace grpc_core {
namespace {
void MaybeAddToBody(const char* field_name, const char* field,
std::vector<std::string>* body) {
void MaybeAddToBody(gpr_strvec* body_strvec, const char* field_name,
const char* field) {
if (field == nullptr || strlen(field) == 0) return;
body->push_back(absl::StrFormat("&%s=%s", field_name, field));
char* new_query;
gpr_asprintf(&new_query, "&%s=%s", field_name, field);
gpr_strvec_add(body_strvec, new_query);
}
grpc_error* LoadTokenFile(const char* path, gpr_slice* token) {
@ -607,18 +608,20 @@ class StsTokenFetcherCredentials
grpc_error* FillBody(char** body, size_t* body_length) {
*body = nullptr;
std::vector<std::string> body_parts;
gpr_strvec body_strvec;
gpr_strvec_init(&body_strvec);
grpc_slice subject_token = grpc_empty_slice();
grpc_slice actor_token = grpc_empty_slice();
grpc_error* err = GRPC_ERROR_NONE;
auto cleanup = [&body, &body_length, &body_parts, &subject_token,
auto cleanup = [&body, &body_length, &body_strvec, &subject_token,
&actor_token, &err]() {
if (err == GRPC_ERROR_NONE) {
std::string body_str = absl::StrJoin(body_parts, "");
*body = gpr_strdup(body_str.c_str());
*body_length = body_str.size();
*body = gpr_strvec_flatten(&body_strvec, body_length);
} else {
gpr_free(*body);
}
gpr_strvec_destroy(&body_strvec);
grpc_slice_unref_internal(subject_token);
grpc_slice_unref_internal(actor_token);
return err;
@ -626,23 +629,23 @@ class StsTokenFetcherCredentials
err = LoadTokenFile(subject_token_path_.get(), &subject_token);
if (err != GRPC_ERROR_NONE) return cleanup();
body_parts.push_back(absl::StrFormat(
GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
gpr_asprintf(
body, GRPC_STS_POST_MINIMAL_BODY_FORMAT_STRING,
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(subject_token)),
subject_token_type_.get()));
MaybeAddToBody("resource", resource_.get(), &body_parts);
MaybeAddToBody("audience", audience_.get(), &body_parts);
MaybeAddToBody("scope", scope_.get(), &body_parts);
MaybeAddToBody("requested_token_type", requested_token_type_.get(),
&body_parts);
subject_token_type_.get());
gpr_strvec_add(&body_strvec, *body);
MaybeAddToBody(&body_strvec, "resource", resource_.get());
MaybeAddToBody(&body_strvec, "audience", audience_.get());
MaybeAddToBody(&body_strvec, "scope", scope_.get());
MaybeAddToBody(&body_strvec, "requested_token_type",
requested_token_type_.get());
if ((actor_token_path_ != nullptr) && *actor_token_path_ != '\0') {
err = LoadTokenFile(actor_token_path_.get(), &actor_token);
if (err != GRPC_ERROR_NONE) return cleanup();
MaybeAddToBody(
"actor_token",
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)),
&body_parts);
MaybeAddToBody("actor_token_type", actor_token_type_.get(), &body_parts);
&body_strvec, "actor_token",
reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(actor_token)));
MaybeAddToBody(&body_strvec, "actor_token_type", actor_token_type_.get());
}
return cleanup();
}

@ -22,90 +22,98 @@
#include <inttypes.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/slice/slice_string_helpers.h"
static void add_metadata(const grpc_metadata* md, size_t count,
std::vector<std::string>* b) {
static void add_metadata(gpr_strvec* b, const grpc_metadata* md, size_t count) {
size_t i;
if (md == nullptr) {
b->push_back("(nil)");
gpr_strvec_add(b, gpr_strdup("(nil)"));
return;
}
for (size_t i = 0; i < count; i++) {
b->push_back("\nkey=");
b->push_back(std::string(grpc_core::StringViewFromSlice(md[i].key)));
b->push_back(" value=");
char* dump = grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII);
b->push_back(dump);
gpr_free(dump);
for (i = 0; i < count; i++) {
gpr_strvec_add(b, gpr_strdup("\nkey="));
gpr_strvec_add(b, grpc_slice_to_c_string(md[i].key));
gpr_strvec_add(b, gpr_strdup(" value="));
gpr_strvec_add(b,
grpc_dump_slice(md[i].value, GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
}
static std::string grpc_op_string(const grpc_op* op) {
std::vector<std::string> parts;
char* grpc_op_string(const grpc_op* op) {
char* tmp;
char* out;
gpr_strvec b;
gpr_strvec_init(&b);
switch (op->op) {
case GRPC_OP_SEND_INITIAL_METADATA:
parts.push_back("SEND_INITIAL_METADATA");
add_metadata(op->data.send_initial_metadata.metadata,
op->data.send_initial_metadata.count, &parts);
gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA"));
add_metadata(&b, op->data.send_initial_metadata.metadata,
op->data.send_initial_metadata.count);
break;
case GRPC_OP_SEND_MESSAGE:
parts.push_back(absl::StrFormat("SEND_MESSAGE ptr=%p",
op->data.send_message.send_message));
gpr_asprintf(&tmp, "SEND_MESSAGE ptr=%p",
op->data.send_message.send_message);
gpr_strvec_add(&b, tmp);
break;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
parts.push_back("SEND_CLOSE_FROM_CLIENT");
gpr_strvec_add(&b, gpr_strdup("SEND_CLOSE_FROM_CLIENT"));
break;
case GRPC_OP_SEND_STATUS_FROM_SERVER:
parts.push_back(
absl::StrFormat("SEND_STATUS_FROM_SERVER status=%d details=",
op->data.send_status_from_server.status));
gpr_asprintf(&tmp, "SEND_STATUS_FROM_SERVER status=%d details=",
op->data.send_status_from_server.status);
gpr_strvec_add(&b, tmp);
if (op->data.send_status_from_server.status_details != nullptr) {
char* dump = grpc_dump_slice(
*op->data.send_status_from_server.status_details, GPR_DUMP_ASCII);
parts.push_back(dump);
gpr_free(dump);
gpr_strvec_add(&b, grpc_dump_slice(
*op->data.send_status_from_server.status_details,
GPR_DUMP_ASCII));
} else {
parts.push_back("(null)");
gpr_strvec_add(&b, gpr_strdup("(null)"));
}
add_metadata(op->data.send_status_from_server.trailing_metadata,
op->data.send_status_from_server.trailing_metadata_count,
&parts);
add_metadata(&b, op->data.send_status_from_server.trailing_metadata,
op->data.send_status_from_server.trailing_metadata_count);
break;
case GRPC_OP_RECV_INITIAL_METADATA:
parts.push_back(absl::StrFormat(
"RECV_INITIAL_METADATA ptr=%p",
op->data.recv_initial_metadata.recv_initial_metadata));
gpr_asprintf(&tmp, "RECV_INITIAL_METADATA ptr=%p",
op->data.recv_initial_metadata.recv_initial_metadata);
gpr_strvec_add(&b, tmp);
break;
case GRPC_OP_RECV_MESSAGE:
parts.push_back(absl::StrFormat("RECV_MESSAGE ptr=%p",
op->data.recv_message.recv_message));
gpr_asprintf(&tmp, "RECV_MESSAGE ptr=%p",
op->data.recv_message.recv_message);
gpr_strvec_add(&b, tmp);
break;
case GRPC_OP_RECV_STATUS_ON_CLIENT:
parts.push_back(absl::StrFormat(
"RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
op->data.recv_status_on_client.trailing_metadata,
op->data.recv_status_on_client.status,
op->data.recv_status_on_client.status_details));
gpr_asprintf(&tmp,
"RECV_STATUS_ON_CLIENT metadata=%p status=%p details=%p",
op->data.recv_status_on_client.trailing_metadata,
op->data.recv_status_on_client.status,
op->data.recv_status_on_client.status_details);
gpr_strvec_add(&b, tmp);
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
parts.push_back(absl::StrFormat("RECV_CLOSE_ON_SERVER cancelled=%p",
op->data.recv_close_on_server.cancelled));
gpr_asprintf(&tmp, "RECV_CLOSE_ON_SERVER cancelled=%p",
op->data.recv_close_on_server.cancelled);
gpr_strvec_add(&b, tmp);
}
return absl::StrJoin(parts, "");
out = gpr_strvec_flatten(&b, nullptr);
gpr_strvec_destroy(&b);
return out;
}
void grpc_call_log_batch(const char* file, int line, gpr_log_severity severity,
const grpc_op* ops, size_t nops) {
for (size_t i = 0; i < nops; i++) {
gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i,
grpc_op_string(&ops[i]).c_str());
char* tmp;
size_t i;
for (i = 0; i < nops; i++) {
tmp = grpc_op_string(&ops[i]);
gpr_log(file, line, severity, "ops[%" PRIuPTR "]: %s", i, tmp);
gpr_free(tmp);
}
}

@ -23,11 +23,6 @@
#include <stdio.h>
#include <string.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
@ -435,14 +430,15 @@ static const cq_vtable g_cq_vtable[] = {
grpc_core::TraceFlag grpc_cq_pluck_trace(false, "queue_pluck");
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
do { \
if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) && \
(GRPC_TRACE_FLAG_ENABLED(grpc_cq_pluck_trace) || \
(event)->type != GRPC_QUEUE_TIMEOUT)) { \
gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, \
grpc_event_string(event).c_str()); \
} \
#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \
do { \
if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) && \
(GRPC_TRACE_FLAG_ENABLED(grpc_cq_pluck_trace) || \
(event)->type != GRPC_QUEUE_TIMEOUT)) { \
char* _ev = grpc_event_string(event); \
gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \
gpr_free(_ev); \
} \
} while (0)
static void on_pollset_shutdown_done(void* cq, grpc_error* error);
@ -955,14 +951,21 @@ class ExecCtxNext : public grpc_core::ExecCtx {
#ifndef NDEBUG
static void dump_pending_tags(grpc_completion_queue* cq) {
if (!GRPC_TRACE_FLAG_ENABLED(grpc_trace_pending_tags)) return;
std::vector<std::string> parts;
parts.push_back("PENDING TAGS:");
gpr_strvec v;
gpr_strvec_init(&v);
gpr_strvec_add(&v, gpr_strdup("PENDING TAGS:"));
gpr_mu_lock(cq->mu);
for (size_t i = 0; i < cq->outstanding_tag_count; i++) {
parts.push_back(absl::StrFormat(" %p", cq->outstanding_tags[i]));
char* s;
gpr_asprintf(&s, " %p", cq->outstanding_tags[i]);
gpr_strvec_add(&v, s);
}
gpr_mu_unlock(cq->mu);
gpr_log(GPR_DEBUG, "%s", absl::StrJoin(parts, "").c_str());
char* out = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
gpr_log(GPR_DEBUG, "%s", out);
gpr_free(out);
}
#else
static void dump_pending_tags(grpc_completion_queue* /*cq*/) {}

@ -22,40 +22,47 @@
#include <stdio.h>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/byte_buffer.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
static void addhdr(grpc_event* ev, std::vector<std::string>* buf) {
buf->push_back(absl::StrFormat("tag:%p", ev->tag));
static void addhdr(gpr_strvec* buf, grpc_event* ev) {
char* tmp;
gpr_asprintf(&tmp, "tag:%p", ev->tag);
gpr_strvec_add(buf, tmp);
}
static const char* errstr(int success) { return success ? "OK" : "ERROR"; }
static void adderr(int success, std::vector<std::string>* buf) {
buf->push_back(absl::StrFormat(" %s", errstr(success)));
static void adderr(gpr_strvec* buf, int success) {
char* tmp;
gpr_asprintf(&tmp, " %s", errstr(success));
gpr_strvec_add(buf, tmp);
}
std::string grpc_event_string(grpc_event* ev) {
if (ev == nullptr) return "null";
std::vector<std::string> out;
char* grpc_event_string(grpc_event* ev) {
char* out;
gpr_strvec buf;
if (ev == nullptr) return gpr_strdup("null");
gpr_strvec_init(&buf);
switch (ev->type) {
case GRPC_QUEUE_TIMEOUT:
out.push_back("QUEUE_TIMEOUT");
gpr_strvec_add(&buf, gpr_strdup("QUEUE_TIMEOUT"));
break;
case GRPC_QUEUE_SHUTDOWN:
out.push_back("QUEUE_SHUTDOWN");
gpr_strvec_add(&buf, gpr_strdup("QUEUE_SHUTDOWN"));
break;
case GRPC_OP_COMPLETE:
out.push_back("OP_COMPLETE: ");
addhdr(ev, &out);
adderr(ev->success, &out);
gpr_strvec_add(&buf, gpr_strdup("OP_COMPLETE: "));
addhdr(&buf, ev);
adderr(&buf, ev->success);
break;
}
return absl::StrJoin(out, "");
out = gpr_strvec_flatten(&buf, nullptr);
gpr_strvec_destroy(&buf);
return out;
}

@ -21,11 +21,9 @@
#include <grpc/support/port_platform.h>
#include <string>
#include <grpc/grpc.h>
/* Returns a string describing an event. Must be later freed with gpr_free() */
std::string grpc_event_string(grpc_event* ev);
char* grpc_event_string(grpc_event* ev);
#endif /* GRPC_CORE_LIB_SURFACE_EVENT_STRING_H */

@ -408,9 +408,8 @@ void grpc_transport_stream_op_batch_finish_with_failure(
grpc_transport_stream_op_batch* op, grpc_error* error,
grpc_core::CallCombiner* call_combiner);
std::string grpc_transport_stream_op_batch_string(
grpc_transport_stream_op_batch* op);
std::string grpc_transport_op_string(grpc_transport_op* op);
char* grpc_transport_stream_op_batch_string(grpc_transport_stream_op_batch* op);
char* grpc_transport_op_string(grpc_transport_op* op);
/* Send a batch of operations on a transport

@ -25,12 +25,6 @@
#include <stdio.h>
#include <string.h>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
@ -40,130 +34,177 @@
/* These routines are here to facilitate debugging - they produce string
representations of various transport data structures */
static void put_metadata(grpc_mdelem md, std::vector<std::string>* out) {
out->push_back("key=");
char* dump = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
out->push_back(dump);
gpr_free(dump);
out->push_back(" value=");
dump = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII);
out->push_back(dump);
gpr_free(dump);
static void put_metadata(gpr_strvec* b, grpc_mdelem md) {
gpr_strvec_add(b, gpr_strdup("key="));
gpr_strvec_add(
b, grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
gpr_strvec_add(b, gpr_strdup(" value="));
gpr_strvec_add(
b, grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII));
}
static void put_metadata_list(grpc_metadata_batch md,
std::vector<std::string>* out) {
static void put_metadata_list(gpr_strvec* b, grpc_metadata_batch md) {
grpc_linked_mdelem* m;
for (m = md.list.head; m != nullptr; m = m->next) {
if (m != md.list.head) out->push_back(", ");
put_metadata(m->md, out);
if (m != md.list.head) gpr_strvec_add(b, gpr_strdup(", "));
put_metadata(b, m->md);
}
if (md.deadline != GRPC_MILLIS_INF_FUTURE) {
out->push_back(absl::StrFormat(" deadline=%" PRId64, md.deadline));
char* tmp;
gpr_asprintf(&tmp, " deadline=%" PRId64, md.deadline);
gpr_strvec_add(b, tmp);
}
}
std::string grpc_transport_stream_op_batch_string(
char* grpc_transport_stream_op_batch_string(
grpc_transport_stream_op_batch* op) {
std::vector<std::string> out;
char* tmp;
char* out;
gpr_strvec b;
gpr_strvec_init(&b);
if (op->send_initial_metadata) {
out.push_back(" SEND_INITIAL_METADATA{");
put_metadata_list(*op->payload->send_initial_metadata.send_initial_metadata,
&out);
out.push_back("}");
gpr_strvec_add(&b, gpr_strdup(" "));
gpr_strvec_add(&b, gpr_strdup("SEND_INITIAL_METADATA{"));
put_metadata_list(
&b, *op->payload->send_initial_metadata.send_initial_metadata);
gpr_strvec_add(&b, gpr_strdup("}"));
}
if (op->send_message) {
gpr_strvec_add(&b, gpr_strdup(" "));
if (op->payload->send_message.send_message != nullptr) {
out.push_back(
absl::StrFormat(" SEND_MESSAGE:flags=0x%08x:len=%d",
op->payload->send_message.send_message->flags(),
op->payload->send_message.send_message->length()));
gpr_asprintf(&tmp, "SEND_MESSAGE:flags=0x%08x:len=%d",
op->payload->send_message.send_message->flags(),
op->payload->send_message.send_message->length());
} else {
// This can happen when we check a batch after the transport has
// processed and cleared the send_message op.
out.push_back(" SEND_MESSAGE(flag and length unknown, already orphaned)");
tmp =
gpr_strdup("SEND_MESSAGE(flag and length unknown, already orphaned)");
}
gpr_strvec_add(&b, tmp);
}
if (op->send_trailing_metadata) {
out.push_back(" SEND_TRAILING_METADATA{");
gpr_strvec_add(&b, gpr_strdup(" "));
gpr_strvec_add(&b, gpr_strdup("SEND_TRAILING_METADATA{"));
put_metadata_list(
*op->payload->send_trailing_metadata.send_trailing_metadata, &out);
out.push_back("}");
&b, *op->payload->send_trailing_metadata.send_trailing_metadata);
gpr_strvec_add(&b, gpr_strdup("}"));
}
if (op->recv_initial_metadata) {
out.push_back(" RECV_INITIAL_METADATA");
gpr_strvec_add(&b, gpr_strdup(" "));
gpr_strvec_add(&b, gpr_strdup("RECV_INITIAL_METADATA"));
}
if (op->recv_message) {
out.push_back(" RECV_MESSAGE");
gpr_strvec_add(&b, gpr_strdup(" "));
gpr_strvec_add(&b, gpr_strdup("RECV_MESSAGE"));
}
if (op->recv_trailing_metadata) {
out.push_back(" RECV_TRAILING_METADATA");
gpr_strvec_add(&b, gpr_strdup(" "));
gpr_strvec_add(&b, gpr_strdup("RECV_TRAILING_METADATA"));
}
if (op->cancel_stream) {
out.push_back(absl::StrCat(
" CANCEL:",
grpc_error_string(op->payload->cancel_stream.cancel_error)));
gpr_strvec_add(&b, gpr_strdup(" "));
const char* msg =
grpc_error_string(op->payload->cancel_stream.cancel_error);
gpr_asprintf(&tmp, "CANCEL:%s", msg);
gpr_strvec_add(&b, tmp);
}
return absl::StrJoin(out, "");
out = gpr_strvec_flatten(&b, nullptr);
gpr_strvec_destroy(&b);
return out;
}
std::string grpc_transport_op_string(grpc_transport_op* op) {
std::vector<std::string> out;
char* grpc_transport_op_string(grpc_transport_op* op) {
char* tmp;
char* out;
bool first = true;
gpr_strvec b;
gpr_strvec_init(&b);
if (op->start_connectivity_watch != nullptr) {
out.push_back(absl::StrFormat(
" START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
gpr_asprintf(
&tmp, "START_CONNECTIVITY_WATCH:watcher=%p:from=%s",
op->start_connectivity_watch.get(),
grpc_core::ConnectivityStateName(op->start_connectivity_watch_state)));
grpc_core::ConnectivityStateName(op->start_connectivity_watch_state));
gpr_strvec_add(&b, tmp);
}
if (op->stop_connectivity_watch != nullptr) {
out.push_back(absl::StrFormat(" STOP_CONNECTIVITY_WATCH:watcher=%p",
op->stop_connectivity_watch));
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
gpr_asprintf(&tmp, "STOP_CONNECTIVITY_WATCH:watcher=%p",
op->stop_connectivity_watch);
gpr_strvec_add(&b, tmp);
}
if (op->disconnect_with_error != GRPC_ERROR_NONE) {
out.push_back(absl::StrCat(" DISCONNECT:",
grpc_error_string(op->disconnect_with_error)));
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
const char* err = grpc_error_string(op->disconnect_with_error);
gpr_asprintf(&tmp, "DISCONNECT:%s", err);
gpr_strvec_add(&b, tmp);
}
if (op->goaway_error) {
out.push_back(
absl::StrCat(" SEND_GOAWAY:%s", grpc_error_string(op->goaway_error)));
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
const char* msg = grpc_error_string(op->goaway_error);
gpr_asprintf(&tmp, "SEND_GOAWAY:%s", msg);
gpr_strvec_add(&b, tmp);
}
if (op->set_accept_stream) {
out.push_back(absl::StrFormat(" SET_ACCEPT_STREAM:%p(%p,...)",
op->set_accept_stream_fn,
op->set_accept_stream_user_data));
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
gpr_asprintf(&tmp, "SET_ACCEPT_STREAM:%p(%p,...)", op->set_accept_stream_fn,
op->set_accept_stream_user_data);
gpr_strvec_add(&b, tmp);
}
if (op->bind_pollset != nullptr) {
out.push_back(" BIND_POLLSET");
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET"));
}
if (op->bind_pollset_set != nullptr) {
out.push_back(" BIND_POLLSET_SET");
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
first = false;
gpr_strvec_add(&b, gpr_strdup("BIND_POLLSET_SET"));
}
if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) {
out.push_back(" SEND_PING");
if (!first) gpr_strvec_add(&b, gpr_strdup(" "));
// first = false;
gpr_strvec_add(&b, gpr_strdup("SEND_PING"));
}
return absl::StrJoin(out, "");
out = gpr_strvec_flatten(&b, nullptr);
gpr_strvec_destroy(&b);
return out;
}
void grpc_call_log_op(const char* file, int line, gpr_log_severity severity,
grpc_call_element* elem,
grpc_transport_stream_op_batch* op) {
gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem,
grpc_transport_stream_op_batch_string(op).c_str());
char* str = grpc_transport_stream_op_batch_string(op);
gpr_log(file, line, severity, "OP[%s:%p]: %s", elem->filter->name, elem, str);
gpr_free(str);
}

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Protobuf-C++'
s.version = '3.11.4'
s.version = '3.12.2'
s.summary = 'Protocol Buffers v3 runtime library for C++.'
s.homepage = 'https://github.com/google/protobuf'
s.license = '3-Clause BSD License'

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta2-18618-05" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
</Project>

@ -2,6 +2,6 @@
<Project>
<PropertyGroup>
<GrpcCsharpVersion>2.30.0-dev</GrpcCsharpVersion>
<GoogleProtobufVersion>3.11.4</GoogleProtobufVersion>
<GoogleProtobufVersion>3.12.2</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -100,7 +100,7 @@ Pod::Spec.new do |s|
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.11.4'
s.dependency '!ProtoCompiler', '3.12.2'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'

@ -102,7 +102,7 @@ Pod::Spec.new do |s|
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.11.4'
s.dependency '!ProtoCompiler', '3.12.2'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'

@ -36,7 +36,7 @@ Pod::Spec.new do |s|
# exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
# before them.
s.name = '!ProtoCompiler'
v = '3.11.4'
v = '3.12.2'
s.version = v
s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files'
s.description = <<-DESC

@ -49,6 +49,7 @@ if [ "$SCHEME" == "tvOS-sample" ]; then
-derivedDataPath Build/Build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO \
| $TEST_PATH/verbose_time.sh \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v "^$" -
@ -61,6 +62,7 @@ else
-derivedDataPath Build/Build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGNING_ALLOWED=NO \
| $TEST_PATH/verbose_time.sh \
| egrep -v "$XCODEBUILD_FILTER" \
| egrep -v "^$" -

@ -46,14 +46,6 @@ $PROTOC --proto_path=. \
src/proto/grpc/testing/empty.proto \
src/proto/grpc/testing/test.proto
# qps test protos
$PROTOC --proto_path=. \
--php_out=src/php/tests/qps/generated_code \
--grpc_out=src/php/tests/qps/generated_code \
--plugin=$PLUGIN \
src/proto/grpc/core/stats.proto \
src/proto/grpc/testing/{benchmark_service,compiler_test,control,echo_messages,empty,empty_service,messages,payloads,proxy-service,report_qps_scenario_service,stats,test,worker_service}.proto
# change it back
sed 's/message EmptyMessage/message Empty/g' \
src/proto/grpc/testing/empty.proto > $output_file
@ -61,3 +53,12 @@ mv $output_file ./src/proto/grpc/testing/empty.proto
sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \
src/proto/grpc/testing/test.proto > $output_file
mv $output_file ./src/proto/grpc/testing/test.proto
# Hack for xDS interop: need this to be a separate file in the correct namespace.
# To be removed when grpc_php_plugin generates service stubs.
echo '<?php
// DO NOT EDIT
namespace Grpc\Testing;
class LoadBalancerStatsServiceStub {
}
' > ./src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php

@ -0,0 +1,168 @@
<?php
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
namespace Grpc;
/**
* This is an experimental and incomplete implementation of gRPC server
* for PHP. APIs are _definitely_ going to be changed.
*
* DO NOT USE in production.
*/
/**
* Class RpcServer
* @package Grpc
*/
class RpcServer extends Server
{
protected $call;
// [ <String method_full_path> => [
// 'service' => <Object service>,
// 'method' => <String method_name>,
// 'request' => <Object request>,
// ] ]
protected $paths_map;
private function waitForNextEvent() {
return $this->requestCall();
}
private function loadRequest($request) {
if (!$this->call) {
throw new Exception("serverCall is not ready");
}
$event = $this->call->startBatch([
OP_RECV_MESSAGE => true,
]);
if (!$event->message) {
throw new Exception("Did not receive a proper message");
}
$request->mergeFromString($event->message);
return $request;
}
protected function sendOkResponse($response) {
if (!$this->call) {
throw new Exception("serverCall is not ready");
}
$this->call->startBatch([
OP_SEND_INITIAL_METADATA => [],
OP_SEND_MESSAGE => ['message' =>
$response->serializeToString()],
OP_SEND_STATUS_FROM_SERVER => [
'metadata' => [],
'code' => STATUS_OK,
'details' => 'OK',
],
OP_RECV_CLOSE_ON_SERVER => true,
]);
}
/**
* Add a service to this server
*
* @param Object $service The service to be added
*/
public function handle($service) {
$rf = new \ReflectionClass($service);
// If input does not have a parent class, which should be the
// generated stub, don't proceeed. This might change in the
// future.
if (!$rf->getParentClass()) return;
// The input class name needs to match the service name
$service_name = $rf->getName();
$namespace = $rf->getParentClass()->getNamespaceName();
$prefix = "";
if ($namespace) {
$parts = explode("\\", $namespace);
foreach ($parts as $part) {
$prefix .= lcfirst($part) . ".";
}
}
$base_path = "/" . $prefix . $service_name;
// Right now, assume all the methods in the class are RPC method
// implementations. Might change in the future.
$methods = $rf->getMethods();
foreach ($methods as $method) {
$method_name = $method->getName();
$full_path = $base_path . "/" . ucfirst($method_name);
$method_params = $method->getParameters();
// RPC should have exactly 1 request param
if (count($method_params) != 1) continue;
$request_param = $method_params[0];
// Method implementation must have type hint for request param
if (!$request_param->getType()) continue;
$request_type = $request_param->getType()->getName();
// $full_path needs to match the incoming event->method
// from requestCall() for us to know how to handle the request
$this->paths_map[$full_path] = [
'service' => $service,
'method' => $method_name,
'request' => new $request_type(),
];
}
}
public function run() {
$this->start();
while (true) {
// This blocks until the server receives a request
$event = $this->waitForNextEvent();
if (!$event) {
throw new Exception(
"Unexpected error: server->waitForNextEvent delivers"
. " an empty event");
}
if (!$event->call) {
throw new Exception(
"Unexpected error: server->waitForNextEvent delivers"
. " an event without a call");
}
$this->call = $event->call;
$full_path = $event->method;
// TODO: Can send a proper UNIMPLEMENTED response in the future
if (!array_key_exists($full_path, $this->paths_map)) continue;
$service = $this->paths_map[$full_path]['service'];
$method = $this->paths_map[$full_path]['method'];
$request = $this->paths_map[$full_path]['request'];
$request = $this->loadRequest($request);
if (!$request) {
throw new Exception("Unexpected error: fail to parse request");
}
if (!method_exists($service, $method)) {
// TODO: Can send a proper UNIMPLEMENTED response in the future
throw new Exception("Method not implemented");
}
// Dispatch to actual server logic
$response = $service->$method($request);
$this->sendOkResponse($response);
$this->call = null;
}
}
}

@ -0,0 +1,6 @@
<?php
// DO NOT EDIT
namespace Grpc\Testing;
class LoadBalancerStatsServiceStub {
}

@ -0,0 +1,151 @@
<?php
/*
*
* Copyright 2020 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* This is the PHP xDS Interop test client. This script is meant to be run by
* the main xDS Interep test runner "run_xds_tests.py", not to be run
* by itself standalone.
*/
$autoload_path = realpath(dirname(__FILE__).'/../../vendor/autoload.php');
require_once $autoload_path;
// The main xds interop test runner will ping this service to ask for
// the stats of the distribution of the backends, for the next X rpcs.
class LoadBalancerStatsService
extends \Grpc\Testing\LoadBalancerStatsServiceStub
{
function getClientStats(\Grpc\Testing\LoadBalancerStatsRequest $request) {
$num_rpcs = $request->getNumRpcs();
$timeout_sec = $request->getTimeoutSec();
$rpcs_by_peer = [];
$num_failures = $num_rpcs;
// Heavy limitation now: the server is blocking, until all
// the necessary num_rpcs are finished, or timeout is reached
global $client_thread;
$start_id = count($client_thread->results) + 1;
$end_id = $start_id + $num_rpcs;
$now = hrtime(true);
$timeout = $now[0] + ($now[1] / 1e9) + $timeout_sec;
while (true) {
$curr_hr = hrtime(true);
$curr_time = $curr_hr[0] + ($curr_hr[1] / 1e9);
if ($curr_time > $timeout) {
break;
}
// Thread variable seems to be read-only
$curr_id = count($client_thread->results);
if ($curr_id >= $end_id) {
break;
}
usleep(50000);
}
// Tally up results
$end_id = min($end_id, count($client_thread->results));
for ($i = $start_id; $i < $end_id; $i++) {
$hostname = $client_thread->results[$i];
if ($hostname) {
$num_failures -= 1;
if (!array_key_exists($hostname, $rpcs_by_peer)) {
$rpcs_by_peer[$hostname] = 0;
}
$rpcs_by_peer[$hostname] += 1;
}
}
$response = new Grpc\Testing\LoadBalancerStatsResponse();
$response->setRpcsByPeer($rpcs_by_peer);
$response->setNumFailures($num_failures);
return $response;
}
}
// This client thread blindly sends a unary RPC to the server once
// every 1 / qps seconds.
class ClientThread extends Thread {
private $server_address_;
private $target_seconds_between_rpcs_;
private $fail_on_failed_rpcs_;
private $autoload_path_;
public $results;
public function __construct($server_address, $qps, $fail_on_failed_rpcs,
$autoload_path) {
$this->server_address_ = $server_address;
$this->target_seconds_between_rpcs_ = 1.0 / $qps;
$this->fail_on_failed_rpcs_ = $fail_on_failed_rpcs;
$this->autoload_path_ = $autoload_path;
$this->results = [];
}
public function run() {
// Autoloaded classes do not get inherited in threads.
// Hence we need to do this.
require_once($this->autoload_path_);
$stub = new Grpc\Testing\TestServiceClient($this->server_address_, [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
$request = new Grpc\Testing\SimpleRequest();
$target_next_start_us = hrtime(true) / 1000;
while (true) {
$now_us = hrtime(true) / 1000;
$sleep_us = $target_next_start_us - $now_us;
if ($sleep_us < 0) {
echo "php xds: warning, rpc takes too long to finish. "
. "If you consistently see this, the qps is too high.\n";
} else {
usleep($sleep_us);
}
$target_next_start_us
+= ($this->target_seconds_between_rpcs_ * 1000000);
list($response, $status)
= $stub->UnaryCall($request)->wait();
if ($status->code == Grpc\STATUS_OK) {
$this->results[] = $response->getHostname();
} else {
if ($this->fail_on_failed_rpcs_) {
throw new Exception('UnaryCall failed with status '
. $status->code);
}
$this->results[] = "";
}
}
}
// This is needed for loading autoload_path in the child thread
public function start(int $options = PTHREADS_INHERIT_ALL) {
return parent::start(PTHREADS_INHERIT_NONE);
}
}
// Note: num_channels are currently ignored for now
$args = getopt('', ['fail_on_failed_rpcs:', 'num_channels:',
'server:', 'stats_port:', 'qps:']);
$client_thread = new ClientThread($args['server'], $args['qps'],
$args['fail_on_failed_rpcs'],
$autoload_path);
$client_thread->start();
$server = new Grpc\RpcServer();
$server->addHttp2Port('0.0.0.0:'.$args['stats_port']);
$server->handle(new LoadBalancerStatsService());
$server->run();

@ -122,7 +122,7 @@ cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
cdef extern from "src/core/lib/iomgr/sockaddr_utils.h":
int grpc_sockaddr_get_port(const grpc_resolved_address *addr);
cppstring grpc_sockaddr_to_string(const grpc_resolved_address *addr,
bool_t normalize);
bool_t normalize);
void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port);
int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
int port)

@ -70,6 +70,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.cc',
'src/core/ext/filters/client_channel/service_config.cc',
'src/core/ext/filters/client_channel/service_config_parser.cc',
'src/core/ext/filters/client_channel/subchannel.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc',

@ -102,7 +102,7 @@ class _GenericHandler(grpc.GenericRpcHandler):
def create_dummy_channel():
"""Creating dummy channels is a workaround for retries"""
host, port, sock = get_socket()
host, port, sock = get_socket(sock_options=(socket.SO_REUSEADDR,))
sock.close()
return grpc.insecure_channel('{}:{}'.format(host, port))
@ -207,7 +207,7 @@ class MetadataFlagsTest(unittest.TestCase):
unhandled_exceptions = queue.Queue()
# We just need an unused TCP port
host, port, sock = get_socket()
host, port, sock = get_socket(sock_options=(socket.SO_REUSEADDR,))
sock.close()
addr = '{}:{}'.format(host, port)

@ -34,7 +34,7 @@
s.require_paths = %w( src/ruby/lib src/ruby/bin src/ruby/pb )
s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.11'
s.add_dependency 'google-protobuf', '~> 3.12'
s.add_dependency 'googleapis-common-protos-types', '~> 1.0'
s.add_development_dependency 'bundler', '>= 1.9'

@ -4,6 +4,6 @@
<Project>
<PropertyGroup>
<GrpcCsharpVersion>${settings.csharp_version}</GrpcCsharpVersion>
<GoogleProtobufVersion>3.11.4</GoogleProtobufVersion>
<GoogleProtobufVersion>3.12.2</GoogleProtobufVersion>
</PropertyGroup>
</Project>

@ -102,7 +102,7 @@
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.11.4'
s.dependency '!ProtoCompiler', '3.12.2'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'

@ -104,7 +104,7 @@
s.preserve_paths = plugin
# Restrict the protoc version to the one supported by this plugin.
s.dependency '!ProtoCompiler', '3.11.4'
s.dependency '!ProtoCompiler', '3.12.2'
# For the Protobuf dependency not to complain:
s.ios.deployment_target = '7.0'
s.osx.deployment_target = '10.9'

@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM alpine:3.5
FROM alpine:3.9
# Install Git and basic packages.
RUN apk update && apk add ${'\\'}

@ -20,9 +20,6 @@
#include <string.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/gpr/string.h"
@ -147,17 +144,22 @@ int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
// Test sending more metadata than the server will accept.
std::vector<std::string> headers;
gpr_strvec headers;
gpr_strvec_init(&headers);
for (i = 0; i < NUM_HEADERS; ++i) {
headers.push_back(absl::StrFormat(
"%s%02d%s", PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i,
PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR));
char* str;
gpr_asprintf(&str, "%s%02d%s",
PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_START_STR, i,
PFX_TOO_MUCH_METADATA_FROM_CLIENT_HEADER_END_STR);
gpr_strvec_add(&headers, str);
}
std::string client_headers = absl::StrJoin(headers, "");
size_t headers_len;
const char* client_headers = gpr_strvec_flatten(&headers, &headers_len);
gpr_strvec_destroy(&headers);
char client_payload[TOO_MUCH_METADATA_FROM_CLIENT_REQUEST_SIZE] =
PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST;
memcpy(client_payload + sizeof(PFX_TOO_MUCH_METADATA_FROM_CLIENT_REQUEST) - 1,
client_headers.data(), client_headers.size());
client_headers, headers_len);
grpc_bad_client_arg args[2];
args[0] = connection_preface_arg;
args[1].client_validator = rst_stream_client_validator;
@ -165,6 +167,7 @@ int main(int argc, char** argv) {
args[1].client_payload_length = sizeof(client_payload) - 1;
grpc_run_bad_client_test(server_verifier_request_call, args, 2, 0);
gpr_free((void*)client_headers);
// Test sending more metadata than the client will accept.
GRPC_RUN_BAD_CLIENT_TEST(server_verifier_sends_too_much_metadata,

@ -34,10 +34,6 @@
#include <grpc/support/string_util.h>
#include <string.h>
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/gpr/string.h"
#include "src/core/lib/surface/channel_init.h"
@ -142,51 +138,64 @@ static int check_stack(const char* file, int line, const char* transport_name,
}
// build up our expectation list
std::vector<std::string> parts;
gpr_strvec v;
gpr_strvec_init(&v);
va_list args;
va_start(args, channel_stack_type);
for (;;) {
char* a = va_arg(args, char*);
if (a == nullptr) break;
parts.push_back(a);
if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", "));
gpr_strvec_add(&v, gpr_strdup(a));
}
va_end(args);
std::string expect = absl::StrJoin(parts, ", ");
char* expect = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
// build up our "got" list
parts.clear();
gpr_strvec_init(&v);
grpc_channel_stack_builder_iterator* it =
grpc_channel_stack_builder_create_iterator_at_first(builder);
while (grpc_channel_stack_builder_move_next(it)) {
const char* name = grpc_channel_stack_builder_iterator_filter_name(it);
if (name == nullptr) continue;
parts.push_back(name);
if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", "));
gpr_strvec_add(&v, gpr_strdup(name));
}
std::string got = absl::StrJoin(parts, ", ");
char* got = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
grpc_channel_stack_builder_iterator_destroy(it);
// figure out result, log if there's an error
int result = 0;
if (got != expect) {
parts.clear();
if (0 != strcmp(got, expect)) {
gpr_strvec_init(&v);
gpr_strvec_add(&v, gpr_strdup("{"));
for (size_t i = 0; i < channel_args->num_args; i++) {
std::string value;
if (i > 0) gpr_strvec_add(&v, gpr_strdup(", "));
gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].key));
gpr_strvec_add(&v, gpr_strdup("="));
switch (channel_args->args[i].type) {
case GRPC_ARG_INTEGER: {
value = absl::StrCat(channel_args->args[i].value.integer);
char* tmp;
gpr_asprintf(&tmp, "%d", channel_args->args[i].value.integer);
gpr_strvec_add(&v, tmp);
break;
}
case GRPC_ARG_STRING:
value = channel_args->args[i].value.string;
gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].value.string));
break;
case GRPC_ARG_POINTER: {
value = absl::StrFormat("%p", channel_args->args[i].value.pointer.p);
char* tmp;
gpr_asprintf(&tmp, "%p", channel_args->args[i].value.pointer.p);
gpr_strvec_add(&v, tmp);
break;
}
}
parts.push_back(absl::StrCat(channel_args->args[i].key, "=", value));
}
std::string args_str = absl::StrCat("{", absl::StrJoin(parts, ", "), "}");
gpr_strvec_add(&v, gpr_strdup("}"));
char* args_str = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR,
"**************************************************");
@ -195,12 +204,17 @@ static int check_stack(const char* file, int line, const char* transport_name,
"FAILED transport=%s; stack_type=%s; channel_args=%s:", transport_name,
grpc_channel_stack_type_string(
static_cast<grpc_channel_stack_type>(channel_stack_type)),
args_str.c_str());
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect.c_str());
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got.c_str());
args_str);
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect);
gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got);
result = 1;
gpr_free(args_str);
}
gpr_free(got);
gpr_free(expect);
{
grpc_core::ExecCtx exec_ctx;
grpc_channel_stack_builder_destroy(builder);

@ -25,6 +25,7 @@
#include <grpc/grpc.h>
#include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
#include "src/core/ext/filters/client_channel/service_config.h"
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/ext/filters/message_size/message_size_filter.h"
#include "src/core/lib/gpr/string.h"
#include "test/core/util/port.h"
@ -33,7 +34,7 @@
namespace grpc_core {
namespace testing {
class TestParsedConfig1 : public ServiceConfig::ParsedConfig {
class TestParsedConfig1 : public ServiceConfigParser::ParsedConfig {
public:
TestParsedConfig1(int value) : value_(value) {}
@ -43,9 +44,9 @@ class TestParsedConfig1 : public ServiceConfig::ParsedConfig {
int value_;
};
class TestParser1 : public ServiceConfig::Parser {
class TestParser1 : public ServiceConfigParser::Parser {
public:
std::unique_ptr<ServiceConfig::ParsedConfig> ParseGlobalParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
const Json& json, grpc_error** error) override {
GPR_DEBUG_ASSERT(error != nullptr);
auto it = json.object_value().find("global_param");
@ -75,9 +76,9 @@ class TestParser1 : public ServiceConfig::Parser {
}
};
class TestParser2 : public ServiceConfig::Parser {
class TestParser2 : public ServiceConfigParser::Parser {
public:
std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
const Json& json, grpc_error** error) override {
GPR_DEBUG_ASSERT(error != nullptr);
auto it = json.object_value().find("method_param");
@ -108,16 +109,16 @@ class TestParser2 : public ServiceConfig::Parser {
};
// This parser always adds errors
class ErrorParser : public ServiceConfig::Parser {
class ErrorParser : public ServiceConfigParser::Parser {
public:
std::unique_ptr<ServiceConfig::ParsedConfig> ParsePerMethodParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams(
const Json& /*json*/, grpc_error** error) override {
GPR_DEBUG_ASSERT(error != nullptr);
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError());
return nullptr;
}
std::unique_ptr<ServiceConfig::ParsedConfig> ParseGlobalParams(
std::unique_ptr<ServiceConfigParser::ParsedConfig> ParseGlobalParams(
const Json& /*json*/, grpc_error** error) override {
GPR_DEBUG_ASSERT(error != nullptr);
*error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError());
@ -139,12 +140,14 @@ void VerifyRegexMatch(grpc_error* error, const std::regex& regex) {
class ServiceConfigTest : public ::testing::Test {
protected:
void SetUp() override {
ServiceConfig::Shutdown();
ServiceConfig::Init();
EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<TestParser1>()),
0);
EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<TestParser2>()),
1);
ServiceConfigParser::Shutdown();
ServiceConfigParser::Init();
EXPECT_EQ(
ServiceConfigParser::RegisterParser(absl::make_unique<TestParser1>()),
0);
EXPECT_EQ(
ServiceConfigParser::RegisterParser(absl::make_unique<TestParser2>()),
1);
}
};
@ -375,12 +378,14 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) {
class ErroredParsersScopingTest : public ::testing::Test {
protected:
void SetUp() override {
ServiceConfig::Shutdown();
ServiceConfig::Init();
EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<ErrorParser>()),
0);
EXPECT_EQ(ServiceConfig::RegisterParser(absl::make_unique<ErrorParser>()),
1);
ServiceConfigParser::Shutdown();
ServiceConfigParser::Init();
EXPECT_EQ(
ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
0);
EXPECT_EQ(
ServiceConfigParser::RegisterParser(absl::make_unique<ErrorParser>()),
1);
}
};
@ -411,10 +416,10 @@ TEST_F(ErroredParsersScopingTest, MethodParams) {
class ClientChannelParserTest : public ::testing::Test {
protected:
void SetUp() override {
ServiceConfig::Shutdown();
ServiceConfig::Init();
ServiceConfigParser::Shutdown();
ServiceConfigParser::Init();
EXPECT_EQ(
ServiceConfig::RegisterParser(
ServiceConfigParser::RegisterParser(
absl::make_unique<internal::ClientChannelServiceConfigParser>()),
0);
}
@ -938,11 +943,11 @@ TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) {
class MessageSizeParserTest : public ::testing::Test {
protected:
void SetUp() override {
ServiceConfig::Shutdown();
ServiceConfig::Init();
EXPECT_EQ(
ServiceConfig::RegisterParser(absl::make_unique<MessageSizeParser>()),
0);
ServiceConfigParser::Shutdown();
ServiceConfigParser::Init();
EXPECT_EQ(ServiceConfigParser::RegisterParser(
absl::make_unique<MessageSizeParser>()),
0);
}
};

@ -23,12 +23,6 @@
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h>
#include <grpc/support/alloc.h>
@ -177,19 +171,21 @@ int byte_buffer_eq_string(grpc_byte_buffer* bb, const char* str) {
static bool is_probably_integer(void* p) { return ((uintptr_t)p) < 1000000; }
namespace {
static void expectation_to_strvec(gpr_strvec* buf, expectation* e) {
char* tmp;
std::string ExpectationString(const expectation& e) {
std::string out;
if (is_probably_integer(e.tag)) {
out = absl::StrFormat("tag(%" PRIdPTR ") ", (intptr_t)e.tag);
if (is_probably_integer(e->tag)) {
gpr_asprintf(&tmp, "tag(%" PRIdPTR ") ", (intptr_t)e->tag);
} else {
out = absl::StrFormat("%p ", e.tag);
gpr_asprintf(&tmp, "%p ", e->tag);
}
switch (e.type) {
gpr_strvec_add(buf, tmp);
switch (e->type) {
case GRPC_OP_COMPLETE:
absl::StrAppendFormat(&out, "GRPC_OP_COMPLETE success=%d %s:%d",
e.success, e.file, e.line);
gpr_asprintf(&tmp, "GRPC_OP_COMPLETE success=%d %s:%d", e->success,
e->file, e->line);
gpr_strvec_add(buf, tmp);
break;
case GRPC_QUEUE_TIMEOUT:
case GRPC_QUEUE_SHUTDOWN:
@ -197,22 +193,27 @@ std::string ExpectationString(const expectation& e) {
abort();
break;
}
return out;
}
std::string ExpectationsString(const cq_verifier& v) {
std::vector<std::string> expectations;
for (expectation* e = v.first_expectation; e != nullptr; e = e->next) {
expectations.push_back(ExpectationString(*e));
static void expectations_to_strvec(gpr_strvec* buf, cq_verifier* v) {
expectation* e;
for (e = v->first_expectation; e != nullptr; e = e->next) {
expectation_to_strvec(buf, e);
gpr_strvec_add(buf, gpr_strdup("\n"));
}
return absl::StrJoin(expectations, "\n");
}
} // namespace
static void fail_no_event_received(cq_verifier* v) {
gpr_log(GPR_ERROR, "no event received, but expected:%s",
ExpectationsString(*v).c_str());
gpr_strvec buf;
char* msg;
gpr_strvec_init(&buf);
gpr_strvec_add(&buf, gpr_strdup("no event received, but expected:\n"));
expectations_to_strvec(&buf, v);
msg = gpr_strvec_flatten(&buf, nullptr);
gpr_log(GPR_ERROR, "%s", msg);
gpr_strvec_destroy(&buf);
gpr_free(msg);
abort();
}
@ -221,8 +222,13 @@ static void verify_matches(expectation* e, grpc_event* ev) {
switch (e->type) {
case GRPC_OP_COMPLETE:
if (e->check_success && e->success != ev->success) {
gpr_log(GPR_ERROR, "actual success does not match expected: %s",
ExpectationString(*e).c_str());
gpr_strvec expected;
gpr_strvec_init(&expected);
expectation_to_strvec(&expected, e);
char* s = gpr_strvec_flatten(&expected, nullptr);
gpr_strvec_destroy(&expected);
gpr_log(GPR_ERROR, "actual success does not match expected: %s", s);
gpr_free(s);
abort();
}
break;
@ -258,9 +264,16 @@ void cq_verify(cq_verifier* v) {
prev = e;
}
if (e == nullptr) {
gpr_log(GPR_ERROR, "cq returned unexpected event: %s",
grpc_event_string(&ev).c_str());
gpr_log(GPR_ERROR, "expected tags:\n%s", ExpectationsString(*v).c_str());
char* s = grpc_event_string(&ev);
gpr_log(GPR_ERROR, "cq returned unexpected event: %s", s);
gpr_free(s);
gpr_strvec expectations;
gpr_strvec_init(&expectations);
expectations_to_strvec(&expectations, v);
s = gpr_strvec_flatten(&expectations, nullptr);
gpr_strvec_destroy(&expectations);
gpr_log(GPR_ERROR, "expected tags:\n%s", s);
gpr_free(s);
abort();
}
}
@ -277,8 +290,9 @@ void cq_verify_empty_timeout(cq_verifier* v, int timeout_sec) {
ev = grpc_completion_queue_next(v->cq, deadline, nullptr);
if (ev.type != GRPC_QUEUE_TIMEOUT) {
gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s",
grpc_event_string(&ev).c_str());
char* s = grpc_event_string(&ev);
gpr_log(GPR_ERROR, "unexpected event (expected nothing): %s", s);
gpr_free(s);
abort();
}
}

@ -151,7 +151,7 @@ static void simple_request_body(grpc_end2end_test_config /*config*/,
op++;
op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
op->data.send_status_from_server.trailing_metadata_count = 0;
op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
op->data.send_status_from_server.status = GRPC_STATUS_OK;
grpc_slice status_details = grpc_slice_from_static_string("xyz");
op->data.send_status_from_server.status_details = &status_details;
op->flags = 0;
@ -170,10 +170,10 @@ static void simple_request_body(grpc_end2end_test_config /*config*/,
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(was_cancelled == 0);
grpc_slice_unref(details);
grpc_metadata_array_destroy(&initial_metadata_recv);

@ -21,8 +21,6 @@
#include <stdio.h>
#include <string.h>
#include <string>
#include <grpc/byte_buffer.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
@ -247,7 +245,9 @@ static void simple_request_body(grpc_end2end_test_config config,
grpc_stats_collect(after);
gpr_log(GPR_DEBUG, "%s", grpc_stats_data_as_json(after).c_str());
char* stats = grpc_stats_data_as_json(after);
gpr_log(GPR_DEBUG, "%s", stats);
gpr_free(stats);
GPR_ASSERT(after->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] -
before->counters[GRPC_STATS_COUNTER_CLIENT_CALLS_CREATED] ==

@ -21,9 +21,6 @@
#include <inttypes.h>
#include <string.h>
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -40,15 +37,20 @@ static void test_noop(void) { Arena::Create(1)->Destroy(); }
static void test(const char* name, size_t init_size, const size_t* allocs,
size_t nallocs) {
std::vector<std::string> parts;
parts.push_back(
absl::StrFormat("test '%s': %" PRIdPTR " <- {", name, init_size));
gpr_strvec v;
char* s;
gpr_strvec_init(&v);
gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
gpr_strvec_add(&v, s);
for (size_t i = 0; i < nallocs; i++) {
parts.push_back(absl::StrFormat("%" PRIdPTR ",", allocs[i]));
gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]);
gpr_strvec_add(&v, s);
}
parts.push_back("}");
std::string s = absl::StrJoin(parts, "");
gpr_log(GPR_INFO, "%s", s.c_str());
gpr_strvec_add(&v, gpr_strdup("}"));
s = gpr_strvec_flatten(&v, nullptr);
gpr_strvec_destroy(&v);
gpr_log(GPR_INFO, "%s", s);
gpr_free(s);
Arena* a = Arena::Create(init_size);
void** ps = static_cast<void**>(gpr_zalloc(sizeof(*ps) * nallocs));

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

Loading…
Cancel
Save