[xDS] avoid creating duplicate hierarchical path attribute values (#34106)

pull/34124/head
Mark D. Roth 1 year ago committed by GitHub
parent 1e818c98bb
commit c0e2fa60f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      BUILD
  2. 5
      CMakeLists.txt
  3. 2
      Makefile
  4. 2
      Package.swift
  5. 10
      build_autogenerated.yaml
  6. 1
      config.m4
  7. 1
      config.w32
  8. 2
      gRPC-C++.podspec
  9. 3
      gRPC-Core.podspec
  10. 2
      grpc.gemspec
  11. 3
      grpc.gyp
  12. 2
      package.xml
  13. 20
      src/core/BUILD
  14. 15
      src/core/ext/filters/client_channel/lb_policy/address_filtering.cc
  15. 12
      src/core/ext/filters/client_channel/lb_policy/address_filtering.h
  16. 7
      src/core/ext/filters/client_channel/lb_policy/priority/priority.cc
  17. 7
      src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc
  18. 11
      src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc
  19. 64
      src/core/lib/channel/channel_args.cc
  20. 96
      src/core/lib/channel/channel_args.h
  21. 1
      src/core/lib/compression/compression_internal.cc
  22. 44
      src/core/lib/gprpp/ref_counted_string.cc
  23. 146
      src/core/lib/gprpp/ref_counted_string.h
  24. 1
      src/python/grpcio/grpc_core_dependencies.py
  25. 2
      tools/doxygen/Doxyfile.c++.internal
  26. 2
      tools/doxygen/Doxyfile.core.internal

@ -1585,6 +1585,7 @@ grpc_cc_library(
"//src/core:promise_status",
"//src/core:race",
"//src/core:ref_counted",
"//src/core:ref_counted_string",
"//src/core:resolved_address",
"//src/core:resource_quota",
"//src/core:resource_quota_trace",

5
CMakeLists.txt generated

@ -2196,6 +2196,7 @@ add_library(grpc
src/core/lib/experiments/experiments.cc
src/core/lib/gprpp/load_file.cc
src/core/lib/gprpp/per_cpu.cc
src/core/lib/gprpp/ref_counted_string.cc
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/time.cc
src/core/lib/gprpp/time_averaged_stats.cc
@ -2901,6 +2902,7 @@ add_library(grpc_unsecure
src/core/lib/experiments/experiments.cc
src/core/lib/gprpp/load_file.cc
src/core/lib/gprpp/per_cpu.cc
src/core/lib/gprpp/ref_counted_string.cc
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/time.cc
src/core/lib/gprpp/time_averaged_stats.cc
@ -4798,6 +4800,7 @@ add_library(grpc_authorization_provider
src/core/lib/experiments/experiments.cc
src/core/lib/gprpp/load_file.cc
src/core/lib/gprpp/per_cpu.cc
src/core/lib/gprpp/ref_counted_string.cc
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/time.cc
src/core/lib/gprpp/time_averaged_stats.cc
@ -10510,6 +10513,7 @@ if(gRPC_BUILD_TESTS)
add_executable(endpoint_config_test
src/core/lib/channel/channel_args.cc
src/core/lib/event_engine/channel_args_endpoint_config.cc
src/core/lib/gprpp/ref_counted_string.cc
src/core/lib/gprpp/time.cc
src/core/lib/surface/channel_stack_type.cc
test/core/event_engine/endpoint_config_test.cc
@ -12091,6 +12095,7 @@ add_executable(frame_test
src/core/lib/experiments/experiments.cc
src/core/lib/gprpp/load_file.cc
src/core/lib/gprpp/per_cpu.cc
src/core/lib/gprpp/ref_counted_string.cc
src/core/lib/gprpp/status_helper.cc
src/core/lib/gprpp/time.cc
src/core/lib/gprpp/time_averaged_stats.cc

2
Makefile generated

@ -1479,6 +1479,7 @@ LIBGRPC_SRC = \
src/core/lib/experiments/experiments.cc \
src/core/lib/gprpp/load_file.cc \
src/core/lib/gprpp/per_cpu.cc \
src/core/lib/gprpp/ref_counted_string.cc \
src/core/lib/gprpp/status_helper.cc \
src/core/lib/gprpp/time.cc \
src/core/lib/gprpp/time_averaged_stats.cc \
@ -2045,6 +2046,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/experiments/experiments.cc \
src/core/lib/gprpp/load_file.cc \
src/core/lib/gprpp/per_cpu.cc \
src/core/lib/gprpp/ref_counted_string.cc \
src/core/lib/gprpp/status_helper.cc \
src/core/lib/gprpp/time.cc \
src/core/lib/gprpp/time_averaged_stats.cc \

2
Package.swift generated

@ -1239,6 +1239,8 @@ let package = Package(
"src/core/lib/gprpp/posix/thd.cc",
"src/core/lib/gprpp/ref_counted.h",
"src/core/lib/gprpp/ref_counted_ptr.h",
"src/core/lib/gprpp/ref_counted_string.cc",
"src/core/lib/gprpp/ref_counted_string.h",
"src/core/lib/gprpp/single_set_ptr.h",
"src/core/lib/gprpp/sorted_pack.h",
"src/core/lib/gprpp/stat.h",

@ -756,6 +756,7 @@ libs:
- src/core/lib/gprpp/per_cpu.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/ref_counted_string.h
- src/core/lib/gprpp/single_set_ptr.h
- src/core/lib/gprpp/sorted_pack.h
- src/core/lib/gprpp/status_helper.h
@ -1550,6 +1551,7 @@ libs:
- src/core/lib/experiments/experiments.cc
- src/core/lib/gprpp/load_file.cc
- src/core/lib/gprpp/per_cpu.cc
- src/core/lib/gprpp/ref_counted_string.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/gprpp/time_averaged_stats.cc
@ -2161,6 +2163,7 @@ libs:
- src/core/lib/gprpp/per_cpu.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/ref_counted_string.h
- src/core/lib/gprpp/single_set_ptr.h
- src/core/lib/gprpp/sorted_pack.h
- src/core/lib/gprpp/status_helper.h
@ -2562,6 +2565,7 @@ libs:
- src/core/lib/experiments/experiments.cc
- src/core/lib/gprpp/load_file.cc
- src/core/lib/gprpp/per_cpu.cc
- src/core/lib/gprpp/ref_counted_string.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/gprpp/time_averaged_stats.cc
@ -4125,6 +4129,7 @@ libs:
- src/core/lib/gprpp/per_cpu.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/ref_counted_string.h
- src/core/lib/gprpp/sorted_pack.h
- src/core/lib/gprpp/status_helper.h
- src/core/lib/gprpp/table.h
@ -4406,6 +4411,7 @@ libs:
- src/core/lib/experiments/experiments.cc
- src/core/lib/gprpp/load_file.cc
- src/core/lib/gprpp/per_cpu.cc
- src/core/lib/gprpp/ref_counted_string.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/gprpp/time_averaged_stats.cc
@ -7644,11 +7650,13 @@ targets:
- src/core/lib/gprpp/orphanable.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/ref_counted_string.h
- src/core/lib/gprpp/time.h
- src/core/lib/surface/channel_stack_type.h
src:
- src/core/lib/channel/channel_args.cc
- src/core/lib/event_engine/channel_args_endpoint_config.cc
- src/core/lib/gprpp/ref_counted_string.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/surface/channel_stack_type.cc
- test/core/event_engine/endpoint_config_test.cc
@ -8770,6 +8778,7 @@ targets:
- src/core/lib/gprpp/per_cpu.h
- src/core/lib/gprpp/ref_counted.h
- src/core/lib/gprpp/ref_counted_ptr.h
- src/core/lib/gprpp/ref_counted_string.h
- src/core/lib/gprpp/sorted_pack.h
- src/core/lib/gprpp/status_helper.h
- src/core/lib/gprpp/table.h
@ -9033,6 +9042,7 @@ targets:
- src/core/lib/experiments/experiments.cc
- src/core/lib/gprpp/load_file.cc
- src/core/lib/gprpp/per_cpu.cc
- src/core/lib/gprpp/ref_counted_string.cc
- src/core/lib/gprpp/status_helper.cc
- src/core/lib/gprpp/time.cc
- src/core/lib/gprpp/time_averaged_stats.cc

1
config.m4 generated

@ -606,6 +606,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gprpp/posix/env.cc \
src/core/lib/gprpp/posix/stat.cc \
src/core/lib/gprpp/posix/thd.cc \
src/core/lib/gprpp/ref_counted_string.cc \
src/core/lib/gprpp/status_helper.cc \
src/core/lib/gprpp/strerror.cc \
src/core/lib/gprpp/tchar.cc \

1
config.w32 generated

@ -571,6 +571,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\gprpp\\posix\\env.cc " +
"src\\core\\lib\\gprpp\\posix\\stat.cc " +
"src\\core\\lib\\gprpp\\posix\\thd.cc " +
"src\\core\\lib\\gprpp\\ref_counted_string.cc " +
"src\\core\\lib\\gprpp\\status_helper.cc " +
"src\\core\\lib\\gprpp\\strerror.cc " +
"src\\core\\lib\\gprpp\\tchar.cc " +

2
gRPC-C++.podspec generated

@ -844,6 +844,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/per_cpu.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/ref_counted_string.h',
'src/core/lib/gprpp/single_set_ptr.h',
'src/core/lib/gprpp/sorted_pack.h',
'src/core/lib/gprpp/stat.h',
@ -1900,6 +1901,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/per_cpu.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/ref_counted_string.h',
'src/core/lib/gprpp/single_set_ptr.h',
'src/core/lib/gprpp/sorted_pack.h',
'src/core/lib/gprpp/stat.h',

3
gRPC-Core.podspec generated

@ -1340,6 +1340,8 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/posix/thd.cc',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/ref_counted_string.cc',
'src/core/lib/gprpp/ref_counted_string.h',
'src/core/lib/gprpp/single_set_ptr.h',
'src/core/lib/gprpp/sorted_pack.h',
'src/core/lib/gprpp/stat.h',
@ -2647,6 +2649,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/per_cpu.h',
'src/core/lib/gprpp/ref_counted.h',
'src/core/lib/gprpp/ref_counted_ptr.h',
'src/core/lib/gprpp/ref_counted_string.h',
'src/core/lib/gprpp/single_set_ptr.h',
'src/core/lib/gprpp/sorted_pack.h',
'src/core/lib/gprpp/stat.h',

2
grpc.gemspec generated

@ -1245,6 +1245,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/posix/thd.cc )
s.files += %w( src/core/lib/gprpp/ref_counted.h )
s.files += %w( src/core/lib/gprpp/ref_counted_ptr.h )
s.files += %w( src/core/lib/gprpp/ref_counted_string.cc )
s.files += %w( src/core/lib/gprpp/ref_counted_string.h )
s.files += %w( src/core/lib/gprpp/single_set_ptr.h )
s.files += %w( src/core/lib/gprpp/sorted_pack.h )
s.files += %w( src/core/lib/gprpp/stat.h )

3
grpc.gyp generated

@ -795,6 +795,7 @@
'src/core/lib/experiments/experiments.cc',
'src/core/lib/gprpp/load_file.cc',
'src/core/lib/gprpp/per_cpu.cc',
'src/core/lib/gprpp/ref_counted_string.cc',
'src/core/lib/gprpp/status_helper.cc',
'src/core/lib/gprpp/time.cc',
'src/core/lib/gprpp/time_averaged_stats.cc',
@ -1301,6 +1302,7 @@
'src/core/lib/experiments/experiments.cc',
'src/core/lib/gprpp/load_file.cc',
'src/core/lib/gprpp/per_cpu.cc',
'src/core/lib/gprpp/ref_counted_string.cc',
'src/core/lib/gprpp/status_helper.cc',
'src/core/lib/gprpp/time.cc',
'src/core/lib/gprpp/time_averaged_stats.cc',
@ -2027,6 +2029,7 @@
'src/core/lib/experiments/experiments.cc',
'src/core/lib/gprpp/load_file.cc',
'src/core/lib/gprpp/per_cpu.cc',
'src/core/lib/gprpp/ref_counted_string.cc',
'src/core/lib/gprpp/status_helper.cc',
'src/core/lib/gprpp/time.cc',
'src/core/lib/gprpp/time_averaged_stats.cc',

2
package.xml generated

@ -1227,6 +1227,8 @@
<file baseinstalldir="/" name="src/core/lib/gprpp/posix/thd.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted_ptr.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted_string.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/ref_counted_string.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/single_set_ptr.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/sorted_pack.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/stat.h" role="src" />

@ -960,6 +960,23 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "ref_counted_string",
srcs = [
"lib/gprpp/ref_counted_string.cc",
],
hdrs = [
"lib/gprpp/ref_counted_string.h",
],
external_deps = ["absl/strings"],
language = "c++",
deps = [
"ref_counted",
"//:gpr",
"//:ref_counted_ptr",
],
)
grpc_cc_library(
name = "uuid_v4",
srcs = ["lib/gprpp/uuid_v4.cc"],
@ -2680,6 +2697,7 @@ grpc_cc_library(
"channel_stack_type",
"dual_ref_counted",
"ref_counted",
"ref_counted_string",
"time",
"useful",
"//:channel_arg_names",
@ -4499,6 +4517,7 @@ grpc_cc_library(
"lb_policy_factory",
"lb_policy_registry",
"pollset_set",
"ref_counted_string",
"validation_errors",
"//:channel_arg_names",
"//:config",
@ -4653,6 +4672,7 @@ grpc_cc_library(
deps = [
"channel_args",
"ref_counted",
"ref_counted_string",
"//:gpr_platform",
"//:ref_counted_ptr",
"//:server_address",

@ -36,7 +36,7 @@ int HierarchicalPathArg::ChannelArgsCompare(const HierarchicalPathArg* a,
const HierarchicalPathArg* b) {
for (size_t i = 0; i < a->path_.size(); ++i) {
if (b->path_.size() == i) return 1;
int r = a->path_[i].compare(b->path_[i]);
int r = a->path_[i].as_string_view().compare(b->path_[i].as_string_view());
if (r != 0) return r;
}
if (b->path_.size() > a->path_.size()) return -1;
@ -47,19 +47,24 @@ absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap(
const absl::StatusOr<ServerAddressList>& addresses) {
if (!addresses.ok()) return addresses.status();
HierarchicalAddressMap result;
RefCountedPtr<HierarchicalPathArg> remaining_path_attr;
for (const ServerAddress& address : *addresses) {
const auto* path_arg = address.args().GetObject<HierarchicalPathArg>();
if (path_arg == nullptr) continue;
const std::vector<std::string>& path = path_arg->path();
const std::vector<RefCountedStringValue>& path = path_arg->path();
auto it = path.begin();
if (it == path.end()) continue;
ServerAddressList& target_list = result[*it];
ChannelArgs args = address.args();
++it;
if (it != path.end()) {
std::vector<std::string> remaining_path(it, path.end());
args = args.SetObject(
MakeRefCounted<HierarchicalPathArg>(std::move(remaining_path)));
std::vector<RefCountedStringValue> remaining_path(it, path.end());
if (remaining_path_attr == nullptr ||
remaining_path_attr->path() != remaining_path) {
remaining_path_attr =
MakeRefCounted<HierarchicalPathArg>(std::move(remaining_path));
}
args = args.SetObject(remaining_path_attr);
}
target_list.emplace_back(address.address(), args);
}

@ -20,7 +20,6 @@
#include <grpc/support/port_platform.h>
#include <map>
#include <string>
#include <utility>
#include <vector>
@ -28,6 +27,7 @@
#include "absl/strings/string_view.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_string.h"
#include "src/core/lib/resolver/server_address.h"
// The resolver returns a flat list of addresses. When a hierarchy of
@ -88,7 +88,7 @@ namespace grpc_core {
// to be associated with the address.
class HierarchicalPathArg : public RefCounted<HierarchicalPathArg> {
public:
explicit HierarchicalPathArg(std::vector<std::string> path)
explicit HierarchicalPathArg(std::vector<RefCountedStringValue> path)
: path_(std::move(path)) {}
// Channel arg traits methods.
@ -96,15 +96,17 @@ class HierarchicalPathArg : public RefCounted<HierarchicalPathArg> {
static int ChannelArgsCompare(const HierarchicalPathArg* a,
const HierarchicalPathArg* b);
const std::vector<std::string>& path() const { return path_; }
const std::vector<RefCountedStringValue>& path() const { return path_; }
private:
std::vector<std::string> path_;
std::vector<RefCountedStringValue> path_;
};
// A map from the next path element to the addresses that fall under
// that path element.
using HierarchicalAddressMap = std::map<std::string, ServerAddressList>;
using HierarchicalAddressMap =
std::map<RefCountedStringValue, ServerAddressList,
RefCountedStringValueLessThan>;
// Splits up the addresses into a separate list for each child.
absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap(

@ -681,7 +681,12 @@ absl::Status PriorityLb::ChildPriority::UpdateLocked(
UpdateArgs update_args;
update_args.config = std::move(config);
if (priority_policy_->addresses_.ok()) {
update_args.addresses = (*priority_policy_->addresses_)[name_];
auto it = priority_policy_->addresses_->find(name_);
if (it == priority_policy_->addresses_->end()) {
update_args.addresses.emplace();
} else {
update_args.addresses = it->second;
}
} else {
update_args.addresses = priority_policy_->addresses_.status();
}

@ -339,7 +339,12 @@ absl::Status WeightedTargetLb::UpdateLocked(UpdateArgs args) {
}
absl::StatusOr<ServerAddressList> addresses;
if (address_map.ok()) {
addresses = std::move((*address_map)[name]);
auto it = address_map->find(name);
if (it == address_map->end()) {
addresses.emplace();
} else {
addresses = std::move(it->second);
}
} else {
addresses = address_map.status();
}

@ -56,6 +56,7 @@
#include "src/core/lib/gprpp/debug_location.h"
#include "src/core/lib/gprpp/orphanable.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/ref_counted_string.h"
#include "src/core/lib/gprpp/validation_errors.h"
#include "src/core/lib/gprpp/work_serializer.h"
#include "src/core/lib/iomgr/pollset_set.h"
@ -764,8 +765,11 @@ ServerAddressList XdsClusterResolverLb::CreateChildPolicyAddressesLocked() {
for (const auto& p : priority_entry.localities) {
const auto& locality_name = p.first;
const auto& locality = p.second;
std::vector<std::string> hierarchical_path = {
priority_child_name, locality_name->AsHumanReadableString()};
std::vector<RefCountedStringValue> hierarchical_path = {
RefCountedStringValue(priority_child_name),
RefCountedStringValue(locality_name->AsHumanReadableString())};
auto hierarchical_path_attr =
MakeRefCounted<HierarchicalPathArg>(std::move(hierarchical_path));
for (const auto& endpoint : locality.endpoints) {
uint32_t endpoint_weight =
locality.lb_weight *
@ -773,8 +777,7 @@ ServerAddressList XdsClusterResolverLb::CreateChildPolicyAddressesLocked() {
addresses.emplace_back(
endpoint.address(),
endpoint.args()
.SetObject(
MakeRefCounted<HierarchicalPathArg>(hierarchical_path))
.SetObject(hierarchical_path_attr)
.Set(GRPC_ARG_ADDRESS_WEIGHT, endpoint_weight)
.SetObject(locality_name->Ref())
.Set(GRPC_ARG_XDS_LOCALITY_WEIGHT, locality.lb_weight));

@ -28,7 +28,6 @@
#include <initializer_list>
#include <map>
#include <memory>
#include <new>
#include <string>
#include <vector>
@ -46,20 +45,6 @@
namespace grpc_core {
RefCountedPtr<RcString> RcString::Make(absl::string_view src) {
void* p = gpr_malloc(sizeof(Header) + src.length() + 1);
return RefCountedPtr<RcString>(new (p) RcString(src));
}
RcString::RcString(absl::string_view src) : header_{{}, src.length()} {
memcpy(payload_, src.data(), header_.length);
// Null terminate because we frequently need to convert to char* still to go
// back and forth to the old c-style api.
payload_[header_.length] = 0;
}
void RcString::Destroy() { gpr_free(this); }
const grpc_arg_pointer_vtable ChannelArgs::Value::int_vtable_{
// copy
[](void* p) { return p; },
@ -74,13 +59,15 @@ const grpc_arg_pointer_vtable ChannelArgs::Value::int_vtable_{
const grpc_arg_pointer_vtable ChannelArgs::Value::string_vtable_{
// copy
[](void* p) -> void* { return static_cast<RcString*>(p)->Ref().release(); },
[](void* p) -> void* {
return static_cast<RefCountedString*>(p)->Ref().release();
},
// destroy
[](void* p) { static_cast<RcString*>(p)->Unref(); },
[](void* p) { static_cast<RefCountedString*>(p)->Unref(); },
// cmp
[](void* p1, void* p2) -> int {
return QsortCompare(static_cast<RcString*>(p1)->as_string_view(),
static_cast<RcString*>(p2)->as_string_view());
return QsortCompare(static_cast<RefCountedString*>(p1)->as_string_view(),
static_cast<RefCountedString*>(p2)->as_string_view());
},
};
@ -139,7 +126,7 @@ bool ChannelArgs::WantMinimalStack() const {
return GetBool(GRPC_ARG_MINIMAL_STACK).value_or(false);
}
ChannelArgs::ChannelArgs(AVL<RcStringValue, Value> args)
ChannelArgs::ChannelArgs(AVL<RefCountedStringValue, Value> args)
: args_(std::move(args)) {}
ChannelArgs ChannelArgs::Set(grpc_arg arg) const {
@ -175,8 +162,8 @@ grpc_arg ChannelArgs::Value::MakeCArg(const char* name) const {
}
if (rep_.c_vtable() == &string_vtable_) {
return grpc_channel_arg_string_create(
c_name,
const_cast<char*>(static_cast<RcString*>(rep_.c_pointer())->c_str()));
c_name, const_cast<char*>(
static_cast<RefCountedString*>(rep_.c_pointer())->c_str()));
}
return grpc_channel_arg_pointer_create(c_name, rep_.c_pointer(),
rep_.c_vtable());
@ -184,9 +171,10 @@ grpc_arg ChannelArgs::Value::MakeCArg(const char* name) const {
ChannelArgs::CPtr ChannelArgs::ToC() const {
std::vector<grpc_arg> c_args;
args_.ForEach([&c_args](const RcStringValue& key, const Value& value) {
c_args.push_back(value.MakeCArg(key.c_str()));
});
args_.ForEach(
[&c_args](const RefCountedStringValue& key, const Value& value) {
c_args.push_back(value.MakeCArg(key.c_str()));
});
return CPtr(static_cast<const grpc_channel_args*>(
grpc_channel_args_copy_and_add(nullptr, c_args.data(), c_args.size())));
}
@ -203,7 +191,7 @@ ChannelArgs ChannelArgs::Set(absl::string_view name, Value value) const {
if (const auto* p = args_.Lookup(name)) {
if (*p == value) return *this; // already have this value for this key
}
return ChannelArgs(args_.Add(RcStringValue(name), std::move(value)));
return ChannelArgs(args_.Add(RefCountedStringValue(name), std::move(value)));
}
ChannelArgs ChannelArgs::Set(absl::string_view name,
@ -227,7 +215,7 @@ ChannelArgs ChannelArgs::Remove(absl::string_view name) const {
ChannelArgs ChannelArgs::RemoveAllKeysWithPrefix(
absl::string_view prefix) const {
auto args = args_;
args_.ForEach([&](const RcStringValue& key, const Value&) {
args_.ForEach([&](const RefCountedStringValue& key, const Value&) {
if (absl::StartsWith(key.as_string_view(), prefix)) args = args.Remove(key);
});
return ChannelArgs(std::move(args));
@ -299,17 +287,18 @@ std::string ChannelArgs::Value::ToString() const {
}
if (rep_.c_vtable() == &string_vtable_) {
return std::string(
static_cast<RcString*>(rep_.c_pointer())->as_string_view());
static_cast<RefCountedString*>(rep_.c_pointer())->as_string_view());
}
return absl::StrFormat("%p", rep_.c_pointer());
}
std::string ChannelArgs::ToString() const {
std::vector<std::string> arg_strings;
args_.ForEach([&arg_strings](const RcStringValue& key, const Value& value) {
arg_strings.push_back(
absl::StrCat(key.as_string_view(), "=", value.ToString()));
});
args_.ForEach(
[&arg_strings](const RefCountedStringValue& key, const Value& value) {
arg_strings.push_back(
absl::StrCat(key.as_string_view(), "=", value.ToString()));
});
return absl::StrCat("{", absl::StrJoin(arg_strings, ", "), "}");
}
@ -317,14 +306,15 @@ ChannelArgs ChannelArgs::UnionWith(ChannelArgs other) const {
if (args_.Empty()) return other;
if (other.args_.Empty()) return *this;
if (args_.Height() <= other.args_.Height()) {
args_.ForEach([&other](const RcStringValue& key, const Value& value) {
other.args_ = other.args_.Add(key, value);
});
args_.ForEach(
[&other](const RefCountedStringValue& key, const Value& value) {
other.args_ = other.args_.Add(key, value);
});
return other;
} else {
auto result = *this;
other.args_.ForEach(
[&result](const RcStringValue& key, const Value& value) {
[&result](const RefCountedStringValue& key, const Value& value) {
if (result.args_.Lookup(key) == nullptr) {
result.args_ = result.args_.Add(key, value);
}
@ -335,7 +325,7 @@ ChannelArgs ChannelArgs::UnionWith(ChannelArgs other) const {
ChannelArgs ChannelArgs::FuzzingReferenceUnionWith(ChannelArgs other) const {
// DO NOT OPTIMIZE THIS!!
args_.ForEach([&other](const RcStringValue& key, const Value& value) {
args_.ForEach([&other](const RefCountedStringValue& key, const Value& value) {
other.args_ = other.args_.Add(key, value);
});
return other;

@ -44,6 +44,7 @@
#include "src/core/lib/gprpp/dual_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_string.h"
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/surface/channel_stack_type.h"
@ -220,91 +221,6 @@ struct GetObjectImpl<T, absl::enable_if_t<!WrapInSharedPtr<T>::value, void>> {
};
};
// Immutable reference counted string
class RcString {
public:
static RefCountedPtr<RcString> Make(absl::string_view src);
RefCountedPtr<RcString> Ref() {
IncrementRefCount();
return RefCountedPtr<RcString>(this);
}
void IncrementRefCount() { header_.rc.Ref(); }
void Unref() {
if (header_.rc.Unref()) Destroy();
}
absl::string_view as_string_view() const {
return absl::string_view(payload_, header_.length);
}
char* c_str() { return payload_; }
private:
explicit RcString(absl::string_view src);
void Destroy();
struct Header {
RefCount rc;
size_t length;
};
Header header_;
char payload_[];
};
// Wrapper around RefCountedPtr<RcString> to give value semantics, especially to
// overloaded operators.
class RcStringValue {
public:
RcStringValue() : str_{} {}
explicit RcStringValue(absl::string_view str) : str_(RcString::Make(str)) {}
absl::string_view as_string_view() const {
return str_ == nullptr ? absl::string_view() : str_->as_string_view();
}
const char* c_str() const { return str_ == nullptr ? "" : str_->c_str(); }
private:
RefCountedPtr<RcString> str_;
};
inline bool operator==(const RcStringValue& lhs, absl::string_view rhs) {
return lhs.as_string_view() == rhs;
}
inline bool operator==(absl::string_view lhs, const RcStringValue& rhs) {
return lhs == rhs.as_string_view();
}
inline bool operator==(const RcStringValue& lhs, const RcStringValue& rhs) {
return lhs.as_string_view() == rhs.as_string_view();
}
inline bool operator<(const RcStringValue& lhs, absl::string_view rhs) {
return lhs.as_string_view() < rhs;
}
inline bool operator<(absl::string_view lhs, const RcStringValue& rhs) {
return lhs < rhs.as_string_view();
}
inline bool operator<(const RcStringValue& lhs, const RcStringValue& rhs) {
return lhs.as_string_view() < rhs.as_string_view();
}
inline bool operator>(const RcStringValue& lhs, absl::string_view rhs) {
return lhs.as_string_view() > rhs;
}
inline bool operator>(absl::string_view lhs, const RcStringValue& rhs) {
return lhs > rhs.as_string_view();
}
inline bool operator>(const RcStringValue& lhs, const RcStringValue& rhs) {
return lhs.as_string_view() > rhs.as_string_view();
}
// Provide the canonical name for a type's channel arg key
template <typename T>
struct ChannelArgNameTraits {
@ -370,16 +286,16 @@ class ChannelArgs {
public:
explicit Value(int n) : rep_(reinterpret_cast<void*>(n), &int_vtable_) {}
explicit Value(std::string s)
: rep_(RcString::Make(s).release(), &string_vtable_) {}
: rep_(RefCountedString::Make(s).release(), &string_vtable_) {}
explicit Value(Pointer p) : rep_(std::move(p)) {}
absl::optional<int> GetIfInt() const {
if (rep_.c_vtable() != &int_vtable_) return absl::nullopt;
return reinterpret_cast<intptr_t>(rep_.c_pointer());
}
RefCountedPtr<RcString> GetIfString() const {
RefCountedPtr<RefCountedString> GetIfString() const {
if (rep_.c_vtable() != &string_vtable_) return nullptr;
return static_cast<RcString*>(rep_.c_pointer())->Ref();
return static_cast<RefCountedString*>(rep_.c_pointer())->Ref();
}
const Pointer* GetIfPointer() const {
if (rep_.c_vtable() == &int_vtable_) return nullptr;
@ -558,12 +474,12 @@ class ChannelArgs {
std::string ToString() const;
private:
explicit ChannelArgs(AVL<RcStringValue, Value> args);
explicit ChannelArgs(AVL<RefCountedStringValue, Value> args);
GRPC_MUST_USE_RESULT ChannelArgs Set(absl::string_view name,
Value value) const;
AVL<RcStringValue, Value> args_;
AVL<RefCountedStringValue, Value> args_;
};
std::ostream& operator<<(std::ostream& out, const ChannelArgs& args);

@ -33,6 +33,7 @@
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/gprpp/ref_counted_string.h"
#include "src/core/lib/surface/api_trace.h"
namespace grpc_core {

@ -0,0 +1,44 @@
//
// Copyright 2023 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/lib/gprpp/ref_counted_string.h"
#include <string.h>
#include <new>
#include <grpc/support/alloc.h>
namespace grpc_core {
RefCountedPtr<RefCountedString> RefCountedString::Make(absl::string_view src) {
void* p = gpr_malloc(sizeof(Header) + src.length() + 1);
return RefCountedPtr<RefCountedString>(new (p) RefCountedString(src));
}
RefCountedString::RefCountedString(absl::string_view src)
: header_{{}, src.length()} {
memcpy(payload_, src.data(), header_.length);
// Null terminate because we frequently need to convert to char* still to go
// back and forth to the old c-style api.
payload_[header_.length] = 0;
}
void RefCountedString::Destroy() { gpr_free(this); }
} // namespace grpc_core

@ -0,0 +1,146 @@
//
// Copyright 2023 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_SRC_CORE_LIB_GPRPP_REF_COUNTED_STRING_H
#define GRPC_SRC_CORE_LIB_GPRPP_REF_COUNTED_STRING_H
#include <grpc/support/port_platform.h>
#include <stddef.h>
#include "absl/strings/string_view.h"
#include "src/core/lib/gprpp/ref_counted.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
namespace grpc_core {
// An immutable reference counted string.
class RefCountedString {
public:
static RefCountedPtr<RefCountedString> Make(absl::string_view src);
// Not copyable.
RefCountedString(const RefCountedString&) = delete;
RefCountedString& operator=(const RefCountedString&) = delete;
// Provide the same interface as RefCounted<>.
// We reimplement this instead of inheritting to make pointer math
// easier in Make().
RefCountedPtr<RefCountedString> Ref() {
IncrementRefCount();
return RefCountedPtr<RefCountedString>(this);
}
void Unref() {
if (header_.rc.Unref()) Destroy();
}
absl::string_view as_string_view() const {
return absl::string_view(payload_, header_.length);
}
char* c_str() { return payload_; }
private:
// Allow RefCountedPtr<> to access IncrementRefCount().
template <typename T>
friend class RefCountedPtr;
explicit RefCountedString(absl::string_view src);
void IncrementRefCount() { header_.rc.Ref(); }
void Destroy();
struct Header {
RefCount rc;
size_t length;
};
Header header_;
char payload_[];
};
// Wrapper around RefCountedPtr<RefCountedString> to give value semantics,
// especially to overloaded operators.
class RefCountedStringValue {
public:
RefCountedStringValue() : str_{} {}
explicit RefCountedStringValue(absl::string_view str)
: str_(RefCountedString::Make(str)) {}
absl::string_view as_string_view() const {
return str_ == nullptr ? absl::string_view() : str_->as_string_view();
}
const char* c_str() const { return str_ == nullptr ? "" : str_->c_str(); }
private:
RefCountedPtr<RefCountedString> str_;
};
inline bool operator==(const RefCountedStringValue& lhs,
absl::string_view rhs) {
return lhs.as_string_view() == rhs;
}
inline bool operator==(absl::string_view lhs,
const RefCountedStringValue& rhs) {
return lhs == rhs.as_string_view();
}
inline bool operator==(const RefCountedStringValue& lhs,
const RefCountedStringValue& rhs) {
return lhs.as_string_view() == rhs.as_string_view();
}
inline bool operator<(const RefCountedStringValue& lhs, absl::string_view rhs) {
return lhs.as_string_view() < rhs;
}
inline bool operator<(absl::string_view lhs, const RefCountedStringValue& rhs) {
return lhs < rhs.as_string_view();
}
inline bool operator<(const RefCountedStringValue& lhs,
const RefCountedStringValue& rhs) {
return lhs.as_string_view() < rhs.as_string_view();
}
inline bool operator>(const RefCountedStringValue& lhs, absl::string_view rhs) {
return lhs.as_string_view() > rhs;
}
inline bool operator>(absl::string_view lhs, const RefCountedStringValue& rhs) {
return lhs > rhs.as_string_view();
}
inline bool operator>(const RefCountedStringValue& lhs,
const RefCountedStringValue& rhs) {
return lhs.as_string_view() > rhs.as_string_view();
}
// A sorting functor to support heterogeneous lookups in sorted containers.
struct RefCountedStringValueLessThan {
using is_transparent = void;
bool operator()(const RefCountedStringValue& lhs,
const RefCountedStringValue& rhs) const {
return lhs < rhs;
}
bool operator()(absl::string_view lhs,
const RefCountedStringValue& rhs) const {
return lhs < rhs;
}
bool operator()(const RefCountedStringValue& lhs,
absl::string_view rhs) const {
return lhs < rhs;
}
};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_LIB_GPRPP_REF_COUNTED_STRING_H

@ -580,6 +580,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/gprpp/posix/env.cc',
'src/core/lib/gprpp/posix/stat.cc',
'src/core/lib/gprpp/posix/thd.cc',
'src/core/lib/gprpp/ref_counted_string.cc',
'src/core/lib/gprpp/status_helper.cc',
'src/core/lib/gprpp/strerror.cc',
'src/core/lib/gprpp/tchar.cc',

@ -2242,6 +2242,8 @@ src/core/lib/gprpp/posix/stat.cc \
src/core/lib/gprpp/posix/thd.cc \
src/core/lib/gprpp/ref_counted.h \
src/core/lib/gprpp/ref_counted_ptr.h \
src/core/lib/gprpp/ref_counted_string.cc \
src/core/lib/gprpp/ref_counted_string.h \
src/core/lib/gprpp/single_set_ptr.h \
src/core/lib/gprpp/sorted_pack.h \
src/core/lib/gprpp/stat.h \

@ -2022,6 +2022,8 @@ src/core/lib/gprpp/posix/stat.cc \
src/core/lib/gprpp/posix/thd.cc \
src/core/lib/gprpp/ref_counted.h \
src/core/lib/gprpp/ref_counted_ptr.h \
src/core/lib/gprpp/ref_counted_string.cc \
src/core/lib/gprpp/ref_counted_string.h \
src/core/lib/gprpp/single_set_ptr.h \
src/core/lib/gprpp/sorted_pack.h \
src/core/lib/gprpp/stat.h \

Loading…
Cancel
Save