|  | @@ -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_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 |