Refactor ServiceConfig code to move parsing to its own API.

pull/23013/head
Mark D. Roth 5 years ago
parent ec8ec630ac
commit aed6574023
  1. 3
      BUILD
  2. 3
      BUILD.gn
  3. 2
      CMakeLists.txt
  4. 2
      Makefile
  5. 6
      build_autogenerated.yaml
  6. 1
      config.m4
  7. 1
      config.w32
  8. 4
      gRPC-C++.podspec
  9. 5
      gRPC-Core.podspec
  10. 3
      grpc.gemspec
  11. 2
      grpc.gyp
  12. 3
      package.xml
  13. 77
      src/core/ext/filters/client_channel/client_channel.cc
  14. 5
      src/core/ext/filters/client_channel/client_channel_plugin.cc
  15. 9
      src/core/ext/filters/client_channel/resolver_result_parsing.cc
  16. 12
      src/core/ext/filters/client_channel/resolver_result_parsing.h
  17. 88
      src/core/ext/filters/client_channel/service_config.cc
  18. 104
      src/core/ext/filters/client_channel/service_config.h
  19. 68
      src/core/ext/filters/client_channel/service_config_call_data.h
  20. 87
      src/core/ext/filters/client_channel/service_config_parser.cc
  21. 89
      src/core/ext/filters/client_channel/service_config_parser.h
  22. 11
      src/core/ext/filters/message_size/message_size_filter.cc
  23. 8
      src/core/ext/filters/message_size/message_size_filter.h
  24. 2
      src/core/lib/channel/context.h
  25. 1
      src/python/grpcio/grpc_core_dependencies.py
  26. 61
      test/core/client_channel/service_config_test.cc
  27. 3
      tools/doxygen/Doxyfile.c++.internal
  28. 3
      tools/doxygen/Doxyfile.core.internal

@ -1044,6 +1044,7 @@ grpc_cc_library(
"src/core/ext/filters/client_channel/retry_throttle.cc", "src/core/ext/filters/client_channel/retry_throttle.cc",
"src/core/ext/filters/client_channel/server_address.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.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.cc",
"src/core/ext/filters/client_channel/subchannel_pool_interface.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/retry_throttle.h",
"src/core/ext/filters/client_channel/server_address.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.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.h",
"src/core/ext/filters/client_channel/subchannel_interface.h", "src/core/ext/filters/client_channel/subchannel_interface.h",
"src/core/ext/filters/client_channel/subchannel_pool_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/server_address.h",
"src/core/ext/filters/client_channel/service_config.cc", "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.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.cc",
"src/core/ext/filters/client_channel/subchannel.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_interface.h",

@ -1374,6 +1374,7 @@ add_library(grpc
src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.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.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.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/client_channel/xds/xds_api.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/retry_throttle.cc
src/core/ext/filters/client_channel/server_address.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.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.cc
src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_channel/subchannel_pool_interface.cc
src/core/ext/filters/client_channel/xds/xds_api.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/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.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.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.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/client_channel/xds/xds_api.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/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.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.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.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/client_channel/xds/xds_api.cc \ src/core/ext/filters/client_channel/xds/xds_api.cc \

@ -411,6 +411,8 @@ libs:
- src/core/ext/filters/client_channel/retry_throttle.h - src/core/ext/filters/client_channel/retry_throttle.h
- src/core/ext/filters/client_channel/server_address.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.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.h
- src/core/ext/filters/client_channel/subchannel_interface.h - src/core/ext/filters/client_channel/subchannel_interface.h
- src/core/ext/filters/client_channel/subchannel_pool_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/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.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.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.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
- src/core/ext/filters/client_channel/xds/xds_api.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/retry_throttle.h
- src/core/ext/filters/client_channel/server_address.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.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.h
- src/core/ext/filters/client_channel/subchannel_interface.h - src/core/ext/filters/client_channel/subchannel_interface.h
- src/core/ext/filters/client_channel/subchannel_pool_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/retry_throttle.cc
- src/core/ext/filters/client_channel/server_address.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.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.cc
- src/core/ext/filters/client_channel/subchannel_pool_interface.cc - src/core/ext/filters/client_channel/subchannel_pool_interface.cc
- src/core/ext/filters/client_channel/xds/xds_api.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/retry_throttle.cc \
src/core/ext/filters/client_channel/server_address.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.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.cc \
src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \
src/core/ext/filters/client_channel/xds/xds_api.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\\retry_throttle.cc " +
"src\\core\\ext\\filters\\client_channel\\server_address.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.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.cc " +
"src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " + "src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " +
"src\\core\\ext\\filters\\client_channel\\xds\\xds_api.cc " + "src\\core\\ext\\filters\\client_channel\\xds\\xds_api.cc " +

@ -261,6 +261,8 @@ Pod::Spec.new do |s|
'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.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.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.h',
'src/core/ext/filters/client_channel/subchannel_interface.h', 'src/core/ext/filters/client_channel/subchannel_interface.h',
'src/core/ext/filters/client_channel/subchannel_pool_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/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.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.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.h',
'src/core/ext/filters/client_channel/subchannel_interface.h', 'src/core/ext/filters/client_channel/subchannel_interface.h',
'src/core/ext/filters/client_channel/subchannel_pool_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/server_address.h',
'src/core/ext/filters/client_channel/service_config.cc', '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.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.cc',
'src/core/ext/filters/client_channel/subchannel.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_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/retry_throttle.h',
'src/core/ext/filters/client_channel/server_address.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.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.h',
'src/core/ext/filters/client_channel/subchannel_interface.h', 'src/core/ext/filters/client_channel/subchannel_interface.h',
'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h',

@ -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/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.cc )
s.files += %w( src/core/ext/filters/client_channel/service_config.h ) 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.cc )
s.files += %w( src/core/ext/filters/client_channel/subchannel.h ) s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
s.files += %w( src/core/ext/filters/client_channel/subchannel_interface.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/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.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.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.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/client_channel/xds/xds_api.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/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.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.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.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc', 'src/core/ext/filters/client_channel/xds/xds_api.cc',

@ -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/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.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.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.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.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_interface.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_interface.h" role="src" />

@ -50,6 +50,7 @@
#include "src/core/ext/filters/client_channel/resolving_lb_policy.h" #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/retry_throttle.h"
#include "src/core/ext/filters/client_channel/service_config.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/client_channel/subchannel.h"
#include "src/core/ext/filters/deadline/deadline_filter.h" #include "src/core/ext/filters/deadline/deadline_filter.h"
#include "src/core/lib/backoff/backoff.h" #include "src/core/lib/backoff/backoff.h"
@ -766,7 +767,6 @@ class CallData {
grpc_call_context_element* call_context_; grpc_call_context_element* call_context_;
RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_; RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
ServiceConfig::CallData service_config_call_data_;
const ClientChannelMethodParsedConfig* method_params_ = nullptr; const ClientChannelMethodParsedConfig* method_params_ = nullptr;
std::map<const char*, absl::string_view> call_attributes_; std::map<const char*, absl::string_view> call_attributes_;
@ -3760,45 +3760,52 @@ void CallData::ApplyServiceConfigToCallLocked(grpc_call_element* elem) {
gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call", gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
chand, this); chand, this);
} }
// Store a ref to the service_config in service_config_call_data_. Also, save auto service_config = chand->service_config();
// a pointer to this in the call_context so that all future filters can access if (service_config != nullptr) {
// it. // Create a ServiceConfigCallData for the call. This stores a ref to the
service_config_call_data_ = // ServiceConfig and caches the right set of parsed configs to use for
ServiceConfig::CallData(chand->service_config(), path_); // the call. The MethodConfig will store itself in the call context,
if (service_config_call_data_.service_config() != nullptr) { // so that it can be accessed by filters in the subchannel, and it
call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = // will be cleaned up when the call ends.
&service_config_call_data_; 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*>( method_params_ = static_cast<ClientChannelMethodParsedConfig*>(
service_config_call_data_.GetMethodParsedConfig( service_config_call_data->GetMethodParsedConfig(
internal::ClientChannelServiceConfigParser::ParserIndex())); internal::ClientChannelServiceConfigParser::ParserIndex()));
} if (method_params_ != nullptr) {
retry_throttle_data_ = chand->retry_throttle_data(); // If the deadline from the service config is shorter than the one
if (method_params_ != nullptr) { // from the client API, reset the deadline timer.
// If the deadline from the service config is shorter than the one if (chand->deadline_checking_enabled() &&
// from the client API, reset the deadline timer. method_params_->timeout() != 0) {
if (chand->deadline_checking_enabled() && method_params_->timeout() != 0) { const grpc_millis per_method_deadline =
const grpc_millis per_method_deadline = grpc_cycle_counter_to_millis_round_up(call_start_time_) +
grpc_cycle_counter_to_millis_round_up(call_start_time_) + method_params_->timeout();
method_params_->timeout(); if (per_method_deadline < deadline_) {
if (per_method_deadline < deadline_) { deadline_ = per_method_deadline;
deadline_ = per_method_deadline; grpc_deadline_state_reset(elem, deadline_);
grpc_deadline_state_reset(elem, deadline_); }
} }
} // If the service config set wait_for_ready and the application
// If the service config set wait_for_ready and the application // did not explicitly set it, use the value from the service config.
// did not explicitly set it, use the value from the service config. uint32_t* send_initial_metadata_flags =
uint32_t* send_initial_metadata_flags = &pending_batches_[0]
&pending_batches_[0] .batch->payload->send_initial_metadata
.batch->payload->send_initial_metadata.send_initial_metadata_flags; .send_initial_metadata_flags;
if (method_params_->wait_for_ready().has_value() && if (method_params_->wait_for_ready().has_value() &&
!(*send_initial_metadata_flags & !(*send_initial_metadata_flags &
GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) { GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) {
if (method_params_->wait_for_ready().value()) { if (method_params_->wait_for_ready().value()) {
*send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY; *send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY;
} else { } else {
*send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; *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. // If no retry policy, disable retries.
// TODO(roth): Remove this when adding support for transparent 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_registry.h"
#include "src/core/ext/filters/client_channel/resolver_result_parsing.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/retry_throttle.h"
#include "src/core/ext/filters/client_channel/service_config_parser.h"
#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/surface/channel_init.h"
static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { 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) { void grpc_client_channel_init(void) {
grpc_core::ServiceConfig::Init(); grpc_core::ServiceConfigParser::Init();
grpc_core::internal::ClientChannelServiceConfigParser::Register(); grpc_core::internal::ClientChannelServiceConfigParser::Register();
grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry(); grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry();
grpc_core::ResolverRegistry::Builder::InitRegistry(); grpc_core::ResolverRegistry::Builder::InitRegistry();
@ -65,5 +66,5 @@ void grpc_client_channel_shutdown(void) {
grpc_core::internal::ServerRetryThrottleMap::Shutdown(); grpc_core::internal::ServerRetryThrottleMap::Shutdown();
grpc_core::ResolverRegistry::Builder::ShutdownRegistry(); grpc_core::ResolverRegistry::Builder::ShutdownRegistry();
grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry(); grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry();
grpc_core::ServiceConfig::Shutdown(); grpc_core::ServiceConfigParser::Shutdown();
} }

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

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

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

@ -26,6 +26,7 @@
#include <grpc/impl/codegen/grpc_types.h> #include <grpc/impl/codegen/grpc_types.h>
#include <grpc/support/string_util.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.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error.h"
@ -58,75 +59,10 @@
namespace grpc_core { 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> { class ServiceConfig : public RefCounted<ServiceConfig> {
public: 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. /// Creates a new service config from parsing \a json_string.
/// Returns null on parse error. /// Returns null on parse error.
static RefCountedPtr<ServiceConfig> Create(absl::string_view json_string, 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 /// Retrieves the global parsed config at index \a index. The
/// lifetime of the returned object is tied to the lifetime of the /// lifetime of the returned object is tied to the lifetime of the
/// ServiceConfig object. /// ServiceConfig object.
ParsedConfig* GetGlobalParsedConfig(size_t index) { ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) {
GPR_DEBUG_ASSERT(index < parsed_global_configs_.size()); GPR_DEBUG_ASSERT(index < parsed_global_configs_.size());
return parsed_global_configs_[index].get(); 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 /// Retrieves the vector of parsed configs for the method identified
/// by \a path. The lifetime of the returned vector and contained objects /// by \a path. The lifetime of the returned vector and contained objects
/// is tied to the lifetime of the ServiceConfig object. /// is tied to the lifetime of the ServiceConfig object.
const ParsedConfigVector* GetMethodParsedConfigVector( const ServiceConfigParser::ParsedConfigVector* GetMethodParsedConfigVector(
const grpc_slice& path) const; 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: private:
// Helper functions to parse the service config // Helper functions for parsing the method configs.
grpc_error* ParseGlobalParams();
grpc_error* ParsePerMethodParams(); grpc_error* ParsePerMethodParams();
grpc_error* ParseJsonMethodConfig(const Json& json);
// Returns a path string for the JSON name object specified by json. // Returns a path string for the JSON name object specified by json.
// Sets *error on error. // Sets *error on error.
static std::string ParseJsonMethodName(const Json& json, grpc_error** error); static std::string ParseJsonMethodName(const Json& json, grpc_error** error);
grpc_error* ParseJsonMethodConfig(const Json& json);
std::string json_string_; std::string json_string_;
Json json_; Json json_;
absl::InlinedVector<std::unique_ptr<ParsedConfig>, kNumPreallocatedParsers> absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfig>,
ServiceConfigParser::kNumPreallocatedParsers>
parsed_global_configs_; parsed_global_configs_;
// A map from the method name to the parsed config vector. Note that we are // 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 // using a raw pointer and not a unique pointer so that we can use the same
// vector for multiple names. // 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_; parsed_method_configs_map_;
// Default method config. // 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 // Storage for all the vectors that are being used in
// parsed_method_configs_table_. // parsed_method_configs_table_.
absl::InlinedVector<std::unique_ptr<ParsedConfigVector>, 32> absl::InlinedVector<std::unique_ptr<ServiceConfigParser::ParsedConfigVector>,
32>
parsed_method_config_vectors_storage_; 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 */

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

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

@ -35,7 +35,7 @@ typedef enum {
/// Reserved for traffic_class_context. /// Reserved for traffic_class_context.
GRPC_CONTEXT_TRAFFIC, 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_SERVICE_CONFIG_CALL_DATA,
GRPC_CONTEXT_COUNT GRPC_CONTEXT_COUNT

@ -70,6 +70,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc',
'src/core/ext/filters/client_channel/server_address.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.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.cc',
'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc',
'src/core/ext/filters/client_channel/xds/xds_api.cc', 'src/core/ext/filters/client_channel/xds/xds_api.cc',

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

@ -1161,6 +1161,9 @@ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/server_address.h \ 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.cc \
src/core/ext/filters/client_channel/service_config.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.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.cc \
src/core/ext/filters/client_channel/subchannel.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_interface.h \

@ -961,6 +961,9 @@ src/core/ext/filters/client_channel/server_address.cc \
src/core/ext/filters/client_channel/server_address.h \ 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.cc \
src/core/ext/filters/client_channel/service_config.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.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.cc \
src/core/ext/filters/client_channel/subchannel.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_interface.h \

Loading…
Cancel
Save