[client channel] use ChunkedVector for call attributes (#33002)

Change call attributes to be stored in a `ChunkedVector` instead of
`std::map<>`, so that the storage can be allocated on the arena. This
means that we're now doing a linear search instead of a map lookup, but
the total number of attributes is expected to be low enough that that
should be okay.

Also, we now hide the actual data structure inside of the
`ServiceConfigCallData` object, which required some changes to the
`ConfigSelector` API. Previously, the `ConfigSelector` would return a
`CallConfig` struct, and the client channel would then use the data in
that struct to populate the `ServiceConfigCallData`. This PR changes
that such that the client channel creates the `ServiceConfigCallData`
before invoking the `ConfigSelector`, and it passes the
`ServiceConfigCallData` into the `ConfigSelector` so that the
`ConfigSelector` can populate it directly.
pull/33008/head
Mark D. Roth 2 years ago committed by GitHub
parent 4c7da485c5
commit 2f89fd5528
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      BUILD
  2. 11
      src/core/BUILD
  3. 21
      src/core/ext/filters/client_channel/client_channel.cc
  4. 29
      src/core/ext/filters/client_channel/client_channel_internal.h
  5. 33
      src/core/ext/filters/client_channel/config_selector.h
  6. 30
      src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc
  7. 50
      src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc
  8. 14
      src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
  9. 61
      src/core/lib/service_config/service_config_call_data.h
  10. 1
      test/core/end2end/BUILD
  11. 1
      test/core/filters/BUILD
  12. 3
      test/cpp/end2end/client_lb_end2end_test.cc

22
BUILD

@ -1204,6 +1204,7 @@ grpc_cc_library(
"grpc_base",
"grpc_public_hdrs",
"grpc_trace",
"legacy_context",
],
)
@ -1355,7 +1356,6 @@ grpc_cc_library(
"//src/core:lib/channel/channelz.h",
"//src/core:lib/channel/channelz_registry.h",
"//src/core:lib/channel/connected_channel.h",
"//src/core:lib/channel/context.h",
"//src/core:lib/channel/promise_based_filter.h",
"//src/core:lib/channel/status_util.h",
"//src/core:lib/compression/compression_internal.h",
@ -1480,6 +1480,7 @@ grpc_cc_library(
"iomgr_buffer_list",
"iomgr_internal_errqueue",
"iomgr_timer",
"legacy_context",
"orphanable",
"parse_address",
"promise",
@ -1569,6 +1570,18 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "legacy_context",
hdrs = [
"//src/core:lib/channel/context.h",
],
language = "c++",
deps = [
"gpr_platform",
"//src/core:context",
],
)
grpc_cc_library(
name = "lb_load_data_store",
srcs = [
@ -1736,6 +1749,7 @@ grpc_cc_library(
"grpc_public_hdrs",
"grpc_trace",
"handshaker",
"legacy_context",
"promise",
"ref_counted_ptr",
"stats",
@ -1895,6 +1909,7 @@ grpc_cc_library(
"grpcpp_call_metric_recorder",
"grpcpp_status",
"iomgr_timer",
"legacy_context",
"ref_counted_ptr",
"//src/core:arena",
"//src/core:channel_args",
@ -1966,6 +1981,7 @@ grpc_cc_library(
"grpcpp_call_metric_recorder",
"grpcpp_status",
"iomgr_timer",
"legacy_context",
"ref_counted_ptr",
"//src/core:arena",
"//src/core:channel_args",
@ -2281,6 +2297,7 @@ grpc_cc_library(
"grpc++_base",
"grpc_base",
"grpc_public_hdrs",
"legacy_context",
"//src/core:arena",
"//src/core:arena_promise",
"//src/core:channel_args",
@ -2951,6 +2968,7 @@ grpc_cc_library(
"grpc_trace",
"http_connect_handshaker",
"iomgr_timer",
"legacy_context",
"orphanable",
"parse_address",
"protobuf_duration_upb",
@ -3455,6 +3473,7 @@ grpc_cc_library(
"grpc_base",
"grpc_public_hdrs",
"grpc_trace",
"legacy_context",
"promise",
"//src/core:activity",
"//src/core:arena",
@ -3827,6 +3846,7 @@ grpc_cc_library(
"http_trace",
"httpcli",
"iomgr_buffer_list",
"legacy_context",
"ref_counted_ptr",
"stats",
"//src/core:arena",

@ -2436,12 +2436,15 @@ grpc_cc_library(
external_deps = ["absl/strings"],
language = "c++",
deps = [
"arena",
"chunked_vector",
"ref_counted",
"service_config_parser",
"slice_refcount",
"unique_type_name",
"useful",
"//:gpr_platform",
"//:legacy_context",
"//:ref_counted_ptr",
],
)
@ -2679,6 +2682,7 @@ grpc_cc_library(
"status_helper",
"//:gpr",
"//:grpc_base",
"//:legacy_context",
"//:promise",
"//:ref_counted_ptr",
],
@ -3583,6 +3587,7 @@ grpc_cc_library(
"//:grpc_base",
"//:grpc_public_hdrs",
"//:grpc_trace",
"//:legacy_context",
],
)
@ -3624,6 +3629,7 @@ grpc_cc_library(
"//:grpc_base",
"//:grpc_public_hdrs",
"//:grpc_trace",
"//:legacy_context",
],
)
@ -3666,6 +3672,7 @@ grpc_cc_library(
"//:grpc_base",
"//:grpc_public_hdrs",
"//:grpc_security_base",
"//:legacy_context",
],
)
@ -3707,6 +3714,7 @@ grpc_cc_library(
"//:gpr",
"//:grpc_base",
"//:grpc_trace",
"//:legacy_context",
],
)
@ -4944,6 +4952,7 @@ grpc_cc_library(
"//:gpr_platform",
"//:grpc_base",
"//:grpc_trace",
"//:legacy_context",
"//:xds_orca_upb",
],
)
@ -5169,7 +5178,6 @@ grpc_cc_library(
"ext/filters/client_channel/resolver/xds/xds_resolver.cc",
],
external_deps = [
"absl/functional:any_invocable",
"absl/meta:type_traits",
"absl/random",
"absl/status",
@ -5637,6 +5645,7 @@ grpc_cc_library(
"//:grpc_client_channel",
"//:grpc_public_hdrs",
"//:grpc_resolver",
"//:legacy_context",
"//:uri_parser",
],
)

@ -1812,23 +1812,22 @@ grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked(
chand(), this);
}
if (!config_selector.ok()) return config_selector.status();
// Use the ConfigSelector to determine the config for the call.
auto call_config =
(*config_selector)->GetCallConfig({send_initial_metadata(), arena()});
if (!call_config.ok()) {
return absl_status_to_grpc_error(
MaybeRewriteIllegalStatusCode(call_config.status(), "ConfigSelector"));
}
// Create a ClientChannelServiceConfigCallData for the call. This stores
// a ref to the ServiceConfig and caches the right set of parsed configs
// to use for the call. The ClientChannelServiceConfigCallData will store
// itself in the call context, so that it can be accessed by filters
// below us in the stack, and it will be cleaned up when the call ends.
auto* service_config_call_data =
arena()->New<ClientChannelServiceConfigCallData>(
std::move(call_config->service_config), call_config->method_configs,
std::move(call_config->call_attributes),
std::move(call_config->on_commit), call_context());
arena()->New<ClientChannelServiceConfigCallData>(arena(), call_context());
// Use the ConfigSelector to determine the config for the call.
absl::Status call_config_status =
(*config_selector)
->GetCallConfig(
{send_initial_metadata(), arena(), service_config_call_data});
if (!call_config_status.ok()) {
return absl_status_to_grpc_error(
MaybeRewriteIllegalStatusCode(call_config_status, "ConfigSelector"));
}
// Apply our own method params to the call.
auto* method_params = static_cast<ClientChannelMethodParsedConfig*>(
service_config_call_data->GetMethodParsedConfig(

@ -23,13 +23,13 @@
#include "absl/functional/any_invocable.h"
#include <grpc/support/log.h>
#include "src/core/lib/channel/context.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/load_balancing/lb_policy.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/service_config/service_config_parser.h"
//
// This file contains internal interfaces used to allow various plugins
@ -54,17 +54,13 @@ class ClientChannelLbCallState : public LoadBalancingPolicy::CallState {
// Internal type for ServiceConfigCallData. Handles call commits.
class ClientChannelServiceConfigCallData : public ServiceConfigCallData {
public:
ClientChannelServiceConfigCallData(
RefCountedPtr<ServiceConfig> service_config,
const ServiceConfigParser::ParsedConfigVector* method_configs,
ServiceConfigCallData::CallAttributes call_attributes,
absl::AnyInvocable<void()> on_commit,
grpc_call_context_element* call_context)
: ServiceConfigCallData(std::move(service_config), method_configs,
std::move(call_attributes)),
on_commit_(std::move(on_commit)) {
call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
ClientChannelServiceConfigCallData(Arena* arena,
grpc_call_context_element* call_context)
: ServiceConfigCallData(arena, call_context) {}
void SetOnCommit(absl::AnyInvocable<void()> on_commit) {
GPR_ASSERT(on_commit_ == nullptr);
on_commit_ = std::move(on_commit);
}
void Commit() {
@ -73,11 +69,6 @@ class ClientChannelServiceConfigCallData : public ServiceConfigCallData {
}
private:
static void Destroy(void* ptr) {
auto* self = static_cast<ClientChannelServiceConfigCallData*>(ptr);
self->~ClientChannelServiceConfigCallData();
}
absl::AnyInvocable<void()> on_commit_;
};

@ -24,21 +24,19 @@
#include <utility>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/status/statusor.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/service_config/service_config_parser.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/metadata_batch.h"
@ -54,20 +52,7 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
struct GetCallConfigArgs {
grpc_metadata_batch* initial_metadata;
Arena* arena;
};
struct CallConfig {
// The per-method parsed configs that will be passed to
// ServiceConfigCallData.
const ServiceConfigParser::ParsedConfigVector* method_configs = nullptr;
// A ref to the service config that contains method_configs, held by
// the call to ensure that method_configs lives long enough.
RefCountedPtr<ServiceConfig> service_config;
// Call attributes that will be accessible to LB policy implementations.
ServiceConfigCallData::CallAttributes call_attributes;
// To be called exactly once, when the call has been committed to a
// particular subchannel (i.e., after all LB picks are complete).
absl::AnyInvocable<void()> on_commit;
ClientChannelServiceConfigCallData* service_config_call_data;
};
~ConfigSelector() override = default;
@ -87,7 +72,7 @@ class ConfigSelector : public RefCounted<ConfigSelector> {
// Returns the call config to use for the call, or a status to fail
// the call with.
virtual absl::StatusOr<CallConfig> GetCallConfig(GetCallConfigArgs args) = 0;
virtual absl::Status GetCallConfig(GetCallConfigArgs args) = 0;
grpc_arg MakeChannelArg() const;
static RefCountedPtr<ConfigSelector> GetFromChannelArgs(
@ -117,14 +102,14 @@ class DefaultConfigSelector : public ConfigSelector {
const char* name() const override { return "default"; }
absl::StatusOr<CallConfig> GetCallConfig(GetCallConfigArgs args) override {
CallConfig call_config;
absl::Status GetCallConfig(GetCallConfigArgs args) override {
Slice* path = args.initial_metadata->get_pointer(HttpPathMetadata());
GPR_ASSERT(path != nullptr);
call_config.method_configs =
auto* parsed_method_configs =
service_config_->GetMethodParsedConfigVector(path->c_slice());
call_config.service_config = service_config_;
return std::move(call_config);
args.service_config_call_data->SetServiceConfig(service_config_,
parsed_method_configs);
return absl::OkStatus();
}
// Only comparing the ConfigSelector itself, not the underlying

@ -29,7 +29,6 @@
#include <utility>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/meta/type_traits.h"
#include "absl/random/random.h"
#include "absl/status/status.h"
@ -47,6 +46,7 @@
#include <grpc/grpc.h>
#include "src/core/ext/filters/client_channel/client_channel_internal.h"
#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/slice/slice.h"
@ -275,7 +275,7 @@ class XdsResolver : public Resolver {
clusters_ == other_xds->clusters_;
}
absl::StatusOr<CallConfig> GetCallConfig(GetCallConfigArgs args) override;
absl::Status GetCallConfig(GetCallConfigArgs args) override;
std::vector<const grpc_channel_filter*> GetFilters() override {
return filters_;
@ -628,8 +628,8 @@ absl::optional<uint64_t> HeaderHashHelper(
return XXH64(header_value->data(), header_value->size(), 0);
}
absl::StatusOr<ConfigSelector::CallConfig>
XdsResolver::XdsConfigSelector::GetCallConfig(GetCallConfigArgs args) {
absl::Status XdsResolver::XdsConfigSelector::GetCallConfig(
GetCallConfigArgs args) {
Slice* path = args.initial_metadata->get_pointer(HttpPathMetadata());
GPR_ASSERT(path != nullptr);
auto route_index = XdsRouting::GetRouteForRequest(
@ -725,25 +725,25 @@ XdsResolver::XdsConfigSelector::GetCallConfig(GetCallConfigArgs args) {
if (!hash.has_value()) {
hash = absl::Uniform<uint64_t>(absl::BitGen());
}
CallConfig call_config;
// Populate service config call data.
if (method_config != nullptr) {
call_config.method_configs =
auto* parsed_method_configs =
method_config->GetMethodParsedConfigVector(grpc_empty_slice());
call_config.service_config = std::move(method_config);
args.service_config_call_data->SetServiceConfig(std::move(method_config),
parsed_method_configs);
}
call_config.call_attributes[XdsClusterAttribute::TypeName()] =
args.arena->New<XdsClusterAttribute>(it->first);
args.service_config_call_data->SetCallAttribute(
args.arena->New<XdsClusterAttribute>(it->first));
std::string hash_string = absl::StrCat(hash.value());
char* hash_value =
static_cast<char*>(args.arena->Alloc(hash_string.size() + 1));
memcpy(hash_value, hash_string.c_str(), hash_string.size());
hash_value[hash_string.size()] = '\0';
call_config.call_attributes[RequestHashAttribute::TypeName()] =
args.arena->New<RequestHashAttribute>(hash_value);
call_config.on_commit = [cluster_state = it->second->Ref()]() mutable {
cluster_state.reset();
};
return std::move(call_config);
args.service_config_call_data->SetCallAttribute(
args.arena->New<RequestHashAttribute>(hash_value));
args.service_config_call_data->SetOnCommit(
[cluster_state = it->second->Ref()]() mutable { cluster_state.reset(); });
return absl::OkStatus();
}
//

@ -34,11 +34,11 @@
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/channel_stack_builder.h"
#include "src/core/lib/channel/context.h"
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/service_config/service_config_impl.h"
@ -75,55 +75,25 @@ class ServiceConfigChannelArgChannelData {
RefCountedPtr<ServiceConfig> service_config_;
};
class ServiceConfigChannelArgCallData {
public:
ServiceConfigChannelArgCallData(
RefCountedPtr<ServiceConfig> service_config,
const ServiceConfigParser::ParsedConfigVector* method_config,
const grpc_call_element_args* args)
: call_context_(args->context),
service_config_call_data_(std::move(service_config), method_config,
/*call_attributes=*/{}) {
GPR_DEBUG_ASSERT(args->context != nullptr);
// No need to set the destroy function, since it will be cleaned up
// when this filter is destroyed in the filter stack.
args->context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value =
&service_config_call_data_;
}
~ServiceConfigChannelArgCallData() {
// Remove the entry from call context, just in case anyone above us
// tries to look at it during call stack destruction.
call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = nullptr;
}
private:
grpc_call_context_element* call_context_;
ServiceConfigCallData service_config_call_data_;
};
grpc_error_handle ServiceConfigChannelArgInitCallElem(
grpc_call_element* elem, const grpc_call_element_args* args) {
auto* chand =
static_cast<ServiceConfigChannelArgChannelData*>(elem->channel_data);
auto* calld = static_cast<ServiceConfigChannelArgCallData*>(elem->call_data);
RefCountedPtr<ServiceConfig> service_config = chand->service_config();
const ServiceConfigParser::ParsedConfigVector* method_config = nullptr;
const ServiceConfigParser::ParsedConfigVector* method_configs = nullptr;
if (service_config != nullptr) {
method_config = service_config->GetMethodParsedConfigVector(args->path);
method_configs = service_config->GetMethodParsedConfigVector(args->path);
}
new (calld) ServiceConfigChannelArgCallData(std::move(service_config),
method_config, args);
auto* service_config_call_data =
args->arena->New<ServiceConfigCallData>(args->arena, args->context);
service_config_call_data->SetServiceConfig(std::move(service_config),
method_configs);
return absl::OkStatus();
}
void ServiceConfigChannelArgDestroyCallElem(
grpc_call_element* elem, const grpc_call_final_info* /* final_info */,
grpc_closure* /* then_schedule_closure */) {
ServiceConfigChannelArgCallData* calld =
static_cast<ServiceConfigChannelArgCallData*>(elem->call_data);
calld->~ServiceConfigChannelArgCallData();
}
grpc_call_element* /*elem*/, const grpc_call_final_info* /*final_info*/,
grpc_closure* /*then_schedule_closure*/) {}
grpc_error_handle ServiceConfigChannelArgInitChannelElem(
grpc_channel_element* elem, grpc_channel_element_args* args) {
@ -143,7 +113,7 @@ const grpc_channel_filter ServiceConfigChannelArgFilter = {
grpc_call_next_op,
nullptr,
grpc_channel_next_op,
sizeof(ServiceConfigChannelArgCallData),
0,
ServiceConfigChannelArgInitCallElem,
grpc_call_stack_ignore_set_pollset_or_pollset_set,
ServiceConfigChannelArgDestroyCallElem,

@ -38,6 +38,7 @@
#include "src/core/lib/promise/context.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/transport/transport.h"
@ -139,14 +140,11 @@ ArenaPromise<ServerMetadataHandle> ServerConfigSelectorFilter::MakeCallPromise(
absl::UnavailableError(StatusToString(call_config.status()))));
return std::move(r);
}
auto& ctx = GetContext<
grpc_call_context_element>()[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA];
ctx.value = GetContext<Arena>()->New<ServiceConfigCallData>(
std::move(call_config->service_config), call_config->method_configs,
ServiceConfigCallData::CallAttributes{});
ctx.destroy = [](void* p) {
static_cast<ServiceConfigCallData*>(p)->~ServiceConfigCallData();
};
auto* service_config_call_data =
GetContext<Arena>()->New<ServiceConfigCallData>(
GetContext<Arena>(), GetContext<grpc_call_context_element>());
service_config_call_data->SetServiceConfig(
std::move(call_config->service_config), call_config->method_configs);
return next_promise_factory(std::move(call_args));
}

@ -21,12 +21,14 @@
#include <stddef.h>
#include <map>
#include <memory>
#include <utility>
#include "src/core/lib/channel/context.h"
#include "src/core/lib/gprpp/chunked_vector.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/unique_type_name.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config.h"
#include "src/core/lib/service_config/service_config_parser.h"
@ -36,6 +38,9 @@ namespace grpc_core {
/// A pointer to this object is stored in the call_context
/// GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA element, so that filters can
/// easily access method and global parameters for the call.
///
/// Must be accessed when holding the call combiner (legacy filter) or from
/// inside the activity (promise-based filter).
class ServiceConfigCallData {
public:
class CallAttributeInterface {
@ -44,45 +49,61 @@ class ServiceConfigCallData {
virtual UniqueTypeName type() const = 0;
};
using CallAttributes = std::map<UniqueTypeName, CallAttributeInterface*>;
ServiceConfigCallData(Arena* arena, grpc_call_context_element* call_context)
: call_attributes_(arena) {
call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value = this;
call_context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].destroy = Destroy;
}
ServiceConfigCallData() : method_configs_(nullptr) {}
virtual ~ServiceConfigCallData() = default;
ServiceConfigCallData(
void SetServiceConfig(
RefCountedPtr<ServiceConfig> service_config,
const ServiceConfigParser::ParsedConfigVector* method_configs,
CallAttributes call_attributes)
: service_config_(std::move(service_config)),
method_configs_(method_configs),
call_attributes_(std::move(call_attributes)) {}
const ServiceConfigParser::ParsedConfigVector* method_configs) {
service_config_ = std::move(service_config);
method_configs_ = method_configs;
}
ServiceConfig* service_config() { return service_config_.get(); }
ServiceConfigParser::ParsedConfig* GetMethodParsedConfig(size_t index) const {
return method_configs_ != nullptr ? (*method_configs_)[index].get()
: nullptr;
if (method_configs_ == nullptr) return nullptr;
return (*method_configs_)[index].get();
}
ServiceConfigParser::ParsedConfig* GetGlobalParsedConfig(size_t index) const {
if (service_config_ == nullptr) return nullptr;
return service_config_->GetGlobalParsedConfig(index);
}
// Must be called when holding the call combiner (legacy filter) or from
// inside the activity (promise-based filter).
void SetCallAttribute(CallAttributeInterface* value) {
call_attributes_.emplace(value->type(), value);
// Overwrite existing entry if we already have one for this type.
for (CallAttributeInterface*& attribute : call_attributes_) {
if (value->type() == attribute->type()) {
attribute = value;
return;
}
}
// Otherwise, add a new entry.
call_attributes_.EmplaceBack(value);
}
CallAttributeInterface* GetCallAttribute(UniqueTypeName name) const {
auto it = call_attributes_.find(name);
if (it == call_attributes_.end()) return nullptr;
return it->second;
CallAttributeInterface* GetCallAttribute(UniqueTypeName type) const {
for (CallAttributeInterface* attribute : call_attributes_) {
if (attribute->type() == type) return attribute;
}
return nullptr;
}
private:
static void Destroy(void* ptr) {
auto* self = static_cast<ServiceConfigCallData*>(ptr);
self->~ServiceConfigCallData();
}
RefCountedPtr<ServiceConfig> service_config_;
const ServiceConfigParser::ParsedConfigVector* method_configs_;
CallAttributes call_attributes_;
const ServiceConfigParser::ParsedConfigVector* method_configs_ = nullptr;
ChunkedVector<CallAttributeInterface*, 4> call_attributes_;
};
} // namespace grpc_core

@ -308,6 +308,7 @@ grpc_cc_test(
"//:grpc_security_base",
"//:grpc_trace",
"//:grpc_unsecure",
"//:legacy_context",
"//:orphanable",
"//:promise",
"//:ref_counted_ptr",

@ -149,6 +149,7 @@ grpc_proto_fuzzer(
"//:grpc_security_base",
"//:handshaker",
"//:iomgr_timer",
"//:legacy_context",
"//:ref_counted_ptr",
"//:tsi_base",
"//src/core:activity",

@ -3098,8 +3098,7 @@ TEST_F(ControlPlaneStatusRewritingTest, RewritesFromConfigSelector) {
bool Equals(const ConfigSelector* other) const override {
return status_ == static_cast<const FailConfigSelector*>(other)->status_;
}
absl::StatusOr<CallConfig> GetCallConfig(
GetCallConfigArgs /*args*/) override {
absl::Status GetCallConfig(GetCallConfigArgs /*args*/) override {
return status_;
}

Loading…
Cancel
Save