Revert "[arena] pool allocator (#31298)" (#31414)

This reverts commit 5e27b2df97.
pull/31415/head
Alisha Nanda 2 years ago committed by GitHub
parent dbc45208e2
commit 2c11e56433
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      BUILD
  2. 38
      CMakeLists.txt
  3. 2
      Makefile
  4. 14
      build_autogenerated.yaml
  5. 1
      config.m4
  6. 1
      config.w32
  7. 2
      gRPC-C++.podspec
  8. 3
      gRPC-Core.podspec
  9. 2
      grpc.gemspec
  10. 2
      grpc.gyp
  11. 2
      package.xml
  12. 1
      src/core/ext/filters/channel_idle/channel_idle_filter.h
  13. 1
      src/core/ext/filters/fault_injection/fault_injection_filter.h
  14. 4
      src/core/ext/filters/http/client/http_client_filter.cc
  15. 1
      src/core/ext/filters/http/client/http_client_filter.h
  16. 2
      src/core/ext/filters/http/client_authority_filter.cc
  17. 1
      src/core/ext/filters/http/client_authority_filter.h
  18. 20
      src/core/ext/filters/http/server/http_server_filter.cc
  19. 1
      src/core/ext/filters/http/server/http_server_filter.h
  20. 2
      src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
  21. 1
      src/core/ext/filters/load_reporting/server_load_reporting_filter.h
  22. 5
      src/core/ext/filters/server_config_selector/server_config_selector_filter.cc
  23. 1
      src/core/lib/channel/channel_stack.h
  24. 10
      src/core/lib/channel/connected_channel.cc
  25. 10
      src/core/lib/channel/promise_based_filter.h
  26. 4
      src/core/lib/promise/call_push_pull.h
  27. 23
      src/core/lib/promise/detail/status.h
  28. 4
      src/core/lib/promise/try_seq.h
  29. 19
      src/core/lib/resource_quota/arena.cc
  30. 89
      src/core/lib/resource_quota/arena.h
  31. 7
      src/core/lib/security/authorization/grpc_server_authz_filter.cc
  32. 1
      src/core/lib/security/authorization/grpc_server_authz_filter.h
  33. 2
      src/core/lib/security/credentials/call_creds_util.h
  34. 2
      src/core/lib/security/credentials/composite/composite_credentials.cc
  35. 2
      src/core/lib/security/credentials/composite/composite_credentials.h
  36. 2
      src/core/lib/security/credentials/fake/fake_credentials.cc
  37. 2
      src/core/lib/security/credentials/fake/fake_credentials.h
  38. 2
      src/core/lib/security/credentials/iam/iam_credentials.cc
  39. 2
      src/core/lib/security/credentials/iam/iam_credentials.h
  40. 2
      src/core/lib/security/credentials/jwt/jwt_credentials.cc
  41. 2
      src/core/lib/security/credentials/jwt/jwt_credentials.h
  42. 1
      src/core/lib/security/credentials/oauth2/oauth2_credentials.cc
  43. 2
      src/core/lib/security/credentials/oauth2/oauth2_credentials.h
  44. 2
      src/core/lib/security/credentials/plugin/plugin_credentials.cc
  45. 2
      src/core/lib/security/credentials/plugin/plugin_credentials.h
  46. 2
      src/core/lib/security/transport/client_auth_filter.cc
  47. 22
      src/core/lib/surface/call.cc
  48. 1
      src/core/lib/surface/call_trace.cc
  49. 3
      src/core/lib/surface/lame_client.cc
  50. 1
      src/core/lib/surface/lame_client.h
  51. 45
      src/core/lib/transport/call_fragments.cc
  52. 232
      src/core/lib/transport/call_fragments.h
  53. 16
      src/core/lib/transport/transport.cc
  54. 57
      src/core/lib/transport/transport.h
  55. 1
      src/core/lib/transport/transport_impl.h
  56. 1
      src/python/grpcio/grpc_core_dependencies.py
  57. 17
      test/core/filters/client_auth_filter_test.cc
  58. 14
      test/core/filters/client_authority_filter_test.cc
  59. 9
      test/core/filters/filter_fuzzer.cc
  60. 45
      test/core/resource_quota/arena_test.cc
  61. 19
      test/core/security/credentials_test.cc
  62. 5
      test/core/security/oauth2_utils.cc
  63. 15
      test/core/transport/BUILD
  64. 96
      test/core/transport/call_fragments_test.cc
  65. 2
      tools/doxygen/Doxyfile.c++.internal
  66. 2
      tools/doxygen/Doxyfile.core.internal
  67. 24
      tools/run_tests/generated/tests.json

@ -2045,10 +2045,6 @@ grpc_cc_library(
hdrs = [
"//src/core:lib/resource_quota/arena.h",
],
external_deps = [
"absl/meta:type_traits",
"absl/utility",
],
deps = [
"construct_destruct",
"context",
@ -3301,6 +3297,7 @@ grpc_cc_library(
"//src/core:lib/surface/server.cc",
"//src/core:lib/surface/validate_metadata.cc",
"//src/core:lib/surface/version.cc",
"//src/core:lib/transport/call_fragments.cc",
"//src/core:lib/transport/connectivity_state.cc",
"//src/core:lib/transport/error_utils.cc",
"//src/core:lib/transport/metadata_batch.cc",
@ -3390,6 +3387,7 @@ grpc_cc_library(
"//src/core:lib/surface/validate_metadata.h",
"//src/core:lib/transport/connectivity_state.h",
"//src/core:lib/transport/metadata_batch.h",
"//src/core:lib/transport/call_fragments.h",
"//src/core:lib/transport/parsed_metadata.h",
"//src/core:lib/transport/status_conversion.h",
"//src/core:lib/transport/timeout_encoding.h",
@ -3483,7 +3481,6 @@ grpc_cc_library(
"poll",
"pollset_set",
"promise",
"promise_status",
"ref_counted",
"ref_counted_ptr",
"resolved_address",

38
CMakeLists.txt generated

@ -847,6 +847,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx byte_buffer_test)
add_dependencies(buildtests_cxx c_slice_buffer_test)
add_dependencies(buildtests_cxx call_finalization_test)
add_dependencies(buildtests_cxx call_fragments_test)
add_dependencies(buildtests_cxx call_push_pull_test)
add_dependencies(buildtests_cxx cancel_ares_query_test)
add_dependencies(buildtests_cxx cel_authorization_engine_test)
@ -2323,6 +2324,7 @@ add_library(grpc
src/core/lib/surface/validate_metadata.cc
src/core/lib/surface/version.cc
src/core/lib/transport/bdp_estimator.cc
src/core/lib/transport/call_fragments.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/handshaker.cc
@ -2899,6 +2901,7 @@ add_library(grpc_unsecure
src/core/lib/surface/validate_metadata.cc
src/core/lib/surface/version.cc
src/core/lib/transport/bdp_estimator.cc
src/core/lib/transport/call_fragments.cc
src/core/lib/transport/connectivity_state.cc
src/core/lib/transport/error_utils.cc
src/core/lib/transport/handshaker.cc
@ -6727,6 +6730,41 @@ target_link_libraries(call_finalization_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(call_fragments_test
test/core/transport/call_fragments_test.cc
third_party/googletest/googletest/src/gtest-all.cc
third_party/googletest/googlemock/src/gmock-all.cc
)
target_include_directories(call_fragments_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(call_fragments_test
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)

2
Makefile generated

@ -1610,6 +1610,7 @@ LIBGRPC_SRC = \
src/core/lib/surface/validate_metadata.cc \
src/core/lib/surface/version.cc \
src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/call_fragments.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/handshaker.cc \
@ -2049,6 +2050,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/surface/validate_metadata.cc \
src/core/lib/surface/version.cc \
src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/call_fragments.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/handshaker.cc \

@ -980,6 +980,7 @@ libs:
- src/core/lib/surface/server.h
- src/core/lib/surface/validate_metadata.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/call_fragments.h
- src/core/lib/transport/connectivity_state.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/handshaker.h
@ -1679,6 +1680,7 @@ libs:
- src/core/lib/surface/validate_metadata.cc
- src/core/lib/surface/version.cc
- src/core/lib/transport/bdp_estimator.cc
- src/core/lib/transport/call_fragments.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/handshaker.cc
@ -2168,6 +2170,7 @@ libs:
- src/core/lib/surface/server.h
- src/core/lib/surface/validate_metadata.h
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/call_fragments.h
- src/core/lib/transport/connectivity_state.h
- src/core/lib/transport/error_utils.h
- src/core/lib/transport/handshaker.h
@ -2500,6 +2503,7 @@ libs:
- src/core/lib/surface/validate_metadata.cc
- src/core/lib/surface/version.cc
- src/core/lib/transport/bdp_estimator.cc
- src/core/lib/transport/call_fragments.cc
- src/core/lib/transport/connectivity_state.cc
- src/core/lib/transport/error_utils.cc
- src/core/lib/transport/handshaker.cc
@ -4503,6 +4507,16 @@ targets:
- test/core/channel/call_finalization_test.cc
deps:
- grpc_test_util
- name: call_fragments_test
gtest: true
build: test
language: c++
headers:
- test/core/promise/test_context.h
src:
- test/core/transport/call_fragments_test.cc
deps:
- grpc_test_util
- name: call_push_pull_test
gtest: true
build: test

1
config.m4 generated

@ -734,6 +734,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/surface/validate_metadata.cc \
src/core/lib/surface/version.cc \
src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/call_fragments.cc \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/error_utils.cc \
src/core/lib/transport/handshaker.cc \

1
config.w32 generated

@ -700,6 +700,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\surface\\validate_metadata.cc " +
"src\\core\\lib\\surface\\version.cc " +
"src\\core\\lib\\transport\\bdp_estimator.cc " +
"src\\core\\lib\\transport\\call_fragments.cc " +
"src\\core\\lib\\transport\\connectivity_state.cc " +
"src\\core\\lib\\transport\\error_utils.cc " +
"src\\core\\lib\\transport\\handshaker.cc " +

2
gRPC-C++.podspec generated

@ -954,6 +954,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_fragments.h',
'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/handshaker.h',
@ -1830,6 +1831,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_fragments.h',
'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/handshaker.h',

3
gRPC-Core.podspec generated

@ -1585,6 +1585,8 @@ Pod::Spec.new do |s|
'src/core/lib/surface/version.cc',
'src/core/lib/transport/bdp_estimator.cc',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_fragments.cc',
'src/core/lib/transport/call_fragments.h',
'src/core/lib/transport/connectivity_state.cc',
'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/error_utils.cc',
@ -2467,6 +2469,7 @@ Pod::Spec.new do |s|
'src/core/lib/surface/server.h',
'src/core/lib/surface/validate_metadata.h',
'src/core/lib/transport/bdp_estimator.h',
'src/core/lib/transport/call_fragments.h',
'src/core/lib/transport/connectivity_state.h',
'src/core/lib/transport/error_utils.h',
'src/core/lib/transport/handshaker.h',

2
grpc.gemspec generated

@ -1496,6 +1496,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/surface/version.cc )
s.files += %w( src/core/lib/transport/bdp_estimator.cc )
s.files += %w( src/core/lib/transport/bdp_estimator.h )
s.files += %w( src/core/lib/transport/call_fragments.cc )
s.files += %w( src/core/lib/transport/call_fragments.h )
s.files += %w( src/core/lib/transport/connectivity_state.cc )
s.files += %w( src/core/lib/transport/connectivity_state.h )
s.files += %w( src/core/lib/transport/error_utils.cc )

2
grpc.gyp generated

@ -1024,6 +1024,7 @@
'src/core/lib/surface/validate_metadata.cc',
'src/core/lib/surface/version.cc',
'src/core/lib/transport/bdp_estimator.cc',
'src/core/lib/transport/call_fragments.cc',
'src/core/lib/transport/connectivity_state.cc',
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/handshaker.cc',
@ -1442,6 +1443,7 @@
'src/core/lib/surface/validate_metadata.cc',
'src/core/lib/surface/version.cc',
'src/core/lib/transport/bdp_estimator.cc',
'src/core/lib/transport/call_fragments.cc',
'src/core/lib/transport/connectivity_state.cc',
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/handshaker.cc',

2
package.xml generated

@ -1478,6 +1478,8 @@
<file baseinstalldir="/" name="src/core/lib/surface/version.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/bdp_estimator.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_fragments.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/call_fragments.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/connectivity_state.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/transport/error_utils.cc" role="src" />

@ -35,6 +35,7 @@
#include "src/core/lib/gprpp/time.h"
#include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/transport.h"

@ -32,6 +32,7 @@
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
// Channel arg key for enabling parsing fault injection via method config.

@ -21,7 +21,6 @@
#include <algorithm>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>
@ -46,6 +45,7 @@
#include "src/core/lib/promise/seq.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/status_conversion.h"
#include "src/core/lib/transport/transport_fwd.h"
#include "src/core/lib/transport/transport_impl.h"
@ -126,7 +126,7 @@ ArenaPromise<ServerMetadataHandle> HttpClientFilter::MakeCallPromise(
Seq(next_promise_factory(std::move(call_args)),
[](ServerMetadataHandle md) -> ServerMetadataHandle {
auto r = CheckServerMetadata(md.get());
if (!r.ok()) return ServerMetadataFromStatus(r);
if (!r.ok()) return ServerMetadataHandle(r);
return md;
}),
[]() { return absl::OkStatus(); },

@ -27,6 +27,7 @@
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"

@ -23,7 +23,6 @@
#include <limits.h>
#include <functional>
#include <memory>
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
@ -36,6 +35,7 @@
#include "src/core/lib/config/core_configuration.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
namespace grpc_core {

@ -30,6 +30,7 @@
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {

@ -21,7 +21,6 @@
#include "src/core/ext/filters/http/server/http_server_filter.h"
#include <functional>
#include <memory>
#include <utility>
#include "absl/base/attributes.h"
@ -41,6 +40,7 @@
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/percent_encoding.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
namespace grpc_core {
@ -75,11 +75,11 @@ ArenaPromise<ServerMetadataHandle> HttpServerFilter::MakeCallPromise(
case HttpMethodMetadata::kInvalid:
case HttpMethodMetadata::kGet:
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Bad method header")));
ServerMetadataHandle(absl::UnknownError("Bad method header")));
}
} else {
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Missing :method header")));
ServerMetadataHandle(absl::UnknownError("Missing :method header")));
}
auto te = md->Take(TeMetadata());
@ -87,21 +87,21 @@ ArenaPromise<ServerMetadataHandle> HttpServerFilter::MakeCallPromise(
// Do nothing, ok.
} else if (!te.has_value()) {
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Missing :te header")));
ServerMetadataHandle(absl::UnknownError("Missing :te header")));
} else {
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Bad :te header")));
ServerMetadataHandle(absl::UnknownError("Bad :te header")));
}
auto scheme = md->Take(HttpSchemeMetadata());
if (scheme.has_value()) {
if (*scheme == HttpSchemeMetadata::kInvalid) {
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Bad :scheme header")));
ServerMetadataHandle(absl::UnknownError("Bad :scheme header")));
}
} else {
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Missing :scheme header")));
ServerMetadataHandle(absl::UnknownError("Missing :scheme header")));
}
md->Remove(ContentTypeMetadata());
@ -109,7 +109,7 @@ ArenaPromise<ServerMetadataHandle> HttpServerFilter::MakeCallPromise(
Slice* path_slice = md->get_pointer(HttpPathMetadata());
if (path_slice == nullptr) {
return Immediate(
ServerMetadataFromStatus(absl::UnknownError("Missing :path header")));
ServerMetadataHandle(absl::UnknownError("Missing :path header")));
}
if (md->get_pointer(HttpAuthorityMetadata()) == nullptr) {
@ -120,8 +120,8 @@ ArenaPromise<ServerMetadataHandle> HttpServerFilter::MakeCallPromise(
}
if (md->get_pointer(HttpAuthorityMetadata()) == nullptr) {
return Immediate(ServerMetadataFromStatus(
absl::UnknownError("Missing :authority header")));
return Immediate(
ServerMetadataHandle(absl::UnknownError("Missing :authority header")));
}
if (!surface_user_agent_) {

@ -27,6 +27,7 @@
#include "src/core/lib/channel/channel_fwd.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {

@ -25,7 +25,6 @@
#include <stdlib.h>
#include <functional>
#include <memory>
#include <string>
#include <utility>
@ -64,6 +63,7 @@
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/surface/channel_init.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/uri/uri_parser.h"
#include "src/cpp/server/load_reporter/constants.h"

@ -30,6 +30,7 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/promise_based_filter.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {

@ -40,6 +40,7 @@
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/service_config/service_config_call_data.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
@ -132,11 +133,11 @@ ServerConfigSelectorFilter::~ServerConfigSelectorFilter() {
ArenaPromise<ServerMetadataHandle> ServerConfigSelectorFilter::MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
auto sel = config_selector();
if (!sel.ok()) return Immediate(ServerMetadataFromStatus(sel.status()));
if (!sel.ok()) return Immediate(ServerMetadataHandle(sel.status()));
auto call_config =
sel.value()->GetCallConfig(call_args.client_initial_metadata.get());
if (!call_config.error.ok()) {
auto r = Immediate(ServerMetadataFromStatus(
auto r = Immediate(ServerMetadataHandle(
absl::UnavailableError(StatusToString(call_config.error))));
return std::move(r);
}

@ -70,6 +70,7 @@
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
struct grpc_channel_element_args {

@ -67,6 +67,7 @@
#include "src/core/lib/surface/call.h"
#include "src/core/lib/surface/call_trace.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/transport_fwd.h"
@ -371,7 +372,7 @@ class ClientStream : public Orphanable {
batch_payload_.send_initial_metadata.peer_string =
GetContext<CallContext>()->peer_string_atm_ptr();
server_initial_metadata_ =
GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
GetContext<FragmentAllocator>()->MakeServerMetadata();
batch_payload_.recv_initial_metadata.recv_initial_metadata =
server_initial_metadata_.get();
batch_payload_.recv_initial_metadata.recv_initial_metadata_ready =
@ -380,7 +381,7 @@ class ClientStream : public Orphanable {
nullptr;
batch_payload_.recv_initial_metadata.peer_string = nullptr;
server_trailing_metadata_ =
GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
GetContext<FragmentAllocator>()->MakeClientMetadata();
batch_payload_.recv_trailing_metadata.recv_trailing_metadata =
server_trailing_metadata_.get();
batch_payload_.recv_trailing_metadata.collect_stats =
@ -420,8 +421,7 @@ class ClientStream : public Orphanable {
} else {
GPR_ASSERT(!absl::holds_alternative<Closed>(send_message_state_));
client_trailing_metadata_ =
GetContext<Arena>()->MakePooled<ClientMetadata>(
GetContext<Arena>());
GetContext<FragmentAllocator>()->MakeClientMetadata();
send_message_state_ = Closed{};
send_message_.send_trailing_metadata = true;
batch_payload_.send_trailing_metadata.send_trailing_metadata =
@ -446,7 +446,7 @@ class ClientStream : public Orphanable {
pending->payload->Length());
}
recv_message_state_ = server_to_client_messages_->Push(
GetContext<Arena>()->MakePooled<Message>(
GetContext<FragmentAllocator>()->MakeMessage(
std::move(*pending->payload), pending->flags));
} else {
if (grpc_call_trace.enabled()) {

@ -60,6 +60,7 @@
#include "src/core/lib/promise/latch.h"
#include "src/core/lib/promise/poll.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
@ -252,15 +253,14 @@ class BaseCallData : public Activity, private Wakeable {
grpc_transport_stream_op_batch* batch_;
};
static Arena::PoolPtr<grpc_metadata_batch> WrapMetadata(
static FragmentHandle<grpc_metadata_batch> WrapMetadata(
grpc_metadata_batch* p) {
return Arena::PoolPtr<grpc_metadata_batch>(p,
Arena::PooledDeleter(nullptr));
return FragmentHandle<grpc_metadata_batch>(p, false);
}
static grpc_metadata_batch* UnwrapMetadata(
Arena::PoolPtr<grpc_metadata_batch> p) {
return p.release();
FragmentHandle<grpc_metadata_batch> p) {
return p.Unwrap();
}
Arena* arena() { return arena_; }

@ -79,7 +79,7 @@ class CallPushPull {
if (IsStatusOk(*status)) {
done_.set(kDonePush);
} else {
return StatusCast<Result>(std::move(*status));
return Result(std::move(*status));
}
}
}
@ -97,7 +97,7 @@ class CallPushPull {
if (IsStatusOk(*status)) {
done_.set(kDonePull);
} else {
return StatusCast<Result>(std::move(*status));
return Result(std::move(*status));
}
}
}

@ -45,29 +45,6 @@ inline absl::Status IntoStatus(absl::Status* status) {
// can participate in TrySeq as result types that affect control flow.
inline bool IsStatusOk(const absl::Status& status) { return status.ok(); }
template <typename To, typename From>
struct StatusCastImpl;
template <typename To>
struct StatusCastImpl<To, To> {
static To Cast(To&& t) { return std::move(t); }
};
template <typename T>
struct StatusCastImpl<absl::StatusOr<T>, absl::Status> {
static absl::StatusOr<T> Cast(absl::Status&& t) { return std::move(t); }
};
template <typename T>
struct StatusCastImpl<absl::StatusOr<T>, const absl::Status&> {
static absl::StatusOr<T> Cast(const absl::Status& t) { return t; }
};
template <typename To, typename From>
To StatusCast(From&& from) {
return StatusCastImpl<To, From>::Cast(std::forward<From>(from));
}
} // namespace grpc_core
#endif // GRPC_CORE_LIB_PROMISE_DETAIL_STATUS_H

@ -69,7 +69,7 @@ struct TrySeqTraitsWithSfinae<absl::StatusOr<T>> {
template <typename Result, typename RunNext>
static Poll<Result> CheckResultAndRunNext(absl::StatusOr<T> prior,
RunNext run_next) {
if (!prior.ok()) return StatusCast<Result>(prior.status());
if (!prior.ok()) return Result(prior.status());
return run_next(std::move(prior));
}
};
@ -105,7 +105,7 @@ struct TrySeqTraitsWithSfinae<absl::Status> {
template <typename Result, typename RunNext>
static Poll<Result> CheckResultAndRunNext(absl::Status prior,
RunNext run_next) {
if (!prior.ok()) return StatusCast<Result>(std::move(prior));
if (!prior.ok()) return Result(std::move(prior));
return run_next(std::move(prior));
}
};

@ -116,23 +116,4 @@ void Arena::ManagedNewObject::Link(std::atomic<ManagedNewObject*>* head) {
}
}
void* Arena::AllocPooled(size_t alloc_size, std::atomic<FreePoolNode*>* head) {
FreePoolNode* p = head->load(std::memory_order_acquire);
while (p != nullptr) {
if (head->compare_exchange_weak(p, p->next, std::memory_order_acq_rel,
std::memory_order_relaxed)) {
return p;
}
}
return Alloc(alloc_size);
}
void Arena::FreePooled(void* p, std::atomic<FreePoolNode*>* head) {
FreePoolNode* node = static_cast<FreePoolNode*>(p);
node->next = head->load(std::memory_order_acquire);
while (!head->compare_exchange_weak(
node->next, node, std::memory_order_acq_rel, std::memory_order_relaxed)) {
}
}
} // namespace grpc_core

@ -31,12 +31,8 @@
#include <atomic>
#include <memory>
#include <new>
#include <utility>
#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"
#include <grpc/event_engine/memory_allocator.h>
#include "src/core/lib/gpr/alloc.h"
@ -46,46 +42,7 @@
namespace grpc_core {
namespace arena_detail {
template <typename Void, size_t kIndex, size_t kObjectSize,
size_t... kBucketSize>
struct PoolIndexForSize;
template <size_t kObjectSize, size_t kIndex, size_t kSmallestRemainingBucket,
size_t... kBucketSizes>
struct PoolIndexForSize<
absl::enable_if_t<kObjectSize <= kSmallestRemainingBucket>, kIndex,
kObjectSize, kSmallestRemainingBucket, kBucketSizes...> {
static constexpr size_t kPool = kIndex;
static constexpr size_t kSize = kSmallestRemainingBucket;
};
template <size_t kObjectSize, size_t kIndex, size_t kSmallestRemainingBucket,
size_t... kBucketSizes>
struct PoolIndexForSize<
absl::enable_if_t<(kObjectSize > kSmallestRemainingBucket)>, kIndex,
kObjectSize, kSmallestRemainingBucket, kBucketSizes...>
: public PoolIndexForSize<void, kIndex + 1, kObjectSize, kBucketSizes...> {
};
template <size_t kObjectSize, size_t... kBucketSizes>
constexpr size_t PoolFromObjectSize(
absl::integer_sequence<size_t, kBucketSizes...>) {
return PoolIndexForSize<void, 0, kObjectSize, kBucketSizes...>::kPool;
}
template <size_t kObjectSize, size_t... kBucketSizes>
constexpr size_t AllocationSizeFromObjectSize(
absl::integer_sequence<size_t, kBucketSizes...>) {
return PoolIndexForSize<void, 0, kObjectSize, kBucketSizes...>::kSize;
}
} // namespace arena_detail
class Arena {
using PoolSizes = absl::integer_sequence<size_t, 256, 512, 768>;
public:
// Create an arena, with \a initial_size bytes in the first allocated buffer.
static Arena* Create(size_t initial_size, MemoryAllocator* memory_allocator);
@ -131,37 +88,6 @@ class Arena {
return &p->t;
}
class PooledDeleter {
public:
explicit PooledDeleter(Arena* arena) : arena_(arena) {}
PooledDeleter() = default;
template <typename T>
void operator()(T* p) {
// TODO(ctiller): promise based filter hijacks ownership of some pointers
// to make them appear as PoolPtr without really transferring ownership,
// by setting the arena to nullptr.
// This is a transitional hack and should be removed once promise based
// filter is removed.
if (arena_ != nullptr) arena_->DeletePooled(p);
}
private:
Arena* arena_;
};
template <typename T>
using PoolPtr = std::unique_ptr<T, PooledDeleter>;
template <typename T, typename... Args>
PoolPtr<T> MakePooled(Args&&... args) {
return PoolPtr<T>(
new (AllocPooled(
arena_detail::AllocationSizeFromObjectSize<sizeof(T)>(PoolSizes()),
&pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())]))
T(std::forward<Args>(args)...),
PooledDeleter(this));
}
private:
struct Zone {
Zone* prev;
@ -202,20 +128,6 @@ class Arena {
void* AllocZone(size_t size);
template <typename T>
void DeletePooled(T* p) {
p->~T();
FreePooled(
p, &pools_[arena_detail::PoolFromObjectSize<sizeof(T)>(PoolSizes())]);
}
struct FreePoolNode {
FreePoolNode* next;
};
void* AllocPooled(size_t alloc_size, std::atomic<FreePoolNode*>* head);
static void FreePooled(void* p, std::atomic<FreePoolNode*>* head);
// Keep track of the total used size. We use this in our call sizing
// hysteresis.
std::atomic<size_t> total_used_{0};
@ -228,7 +140,6 @@ class Arena {
// last zone; the zone list is reverse-walked during arena destruction only.
std::atomic<Zone*> last_zone_{nullptr};
std::atomic<ManagedNewObject*> managed_new_head_{nullptr};
std::atomic<FreePoolNode*> pools_[PoolSizes::size()]{};
// The backing memory quota
MemoryAllocator* const memory_allocator_;
};

@ -17,7 +17,6 @@
#include "src/core/lib/security/authorization/grpc_server_authz_filter.h"
#include <functional>
#include <memory>
#include <string>
#include <utility>
@ -33,6 +32,7 @@
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/authorization/authorization_engine.h"
#include "src/core/lib/security/authorization/evaluate_args.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {
@ -108,9 +108,8 @@ bool GrpcServerAuthzFilter::IsAuthorized(
ArenaPromise<ServerMetadataHandle> GrpcServerAuthzFilter::MakeCallPromise(
CallArgs call_args, NextPromiseFactory next_promise_factory) {
if (!IsAuthorized(call_args.client_initial_metadata)) {
return ArenaPromise<ServerMetadataHandle>(
Immediate(ServerMetadataFromStatus(absl::PermissionDeniedError(
"Unauthorized RPC request rejected."))));
return ArenaPromise<ServerMetadataHandle>(Immediate(ServerMetadataHandle(
absl::PermissionDeniedError("Unauthorized RPC request rejected."))));
}
return next_promise_factory(std::move(call_args));
}

@ -30,6 +30,7 @@
#include "src/core/lib/security/authorization/authorization_policy_provider.h"
#include "src/core/lib/security/authorization/evaluate_args.h"
#include "src/core/lib/security/context/security_context.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
namespace grpc_core {

@ -24,7 +24,7 @@
#include <grpc/grpc_security.h>
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
namespace grpc_core {

@ -21,7 +21,6 @@
#include "src/core/lib/security/credentials/composite/composite_credentials.h"
#include <cstring>
#include <memory>
#include <vector>
#include "absl/strings/str_cat.h"
@ -34,6 +33,7 @@
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/promise/try_seq.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/call_fragments.h"
//
// grpc_composite_channel_credentials

@ -39,7 +39,7 @@
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/security_connector/security_connector.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
/* -- Composite channel credentials. -- */

@ -22,7 +22,6 @@
#include <stdlib.h>
#include <memory>
#include <utility>
#include "absl/strings/string_view.h"
@ -32,6 +31,7 @@
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/security_connector/fake/fake_security_connector.h"
#include "src/core/lib/security/security_connector/security_connector.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
/* -- Fake transport security credentials. -- */

@ -35,7 +35,7 @@
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
#define GRPC_ARG_FAKE_SECURITY_EXPECTED_TARGETS \
"grpc.fake_security.expected_targets"

@ -22,7 +22,6 @@
#include <stdlib.h>
#include <memory>
#include <utility>
#include "absl/strings/str_format.h"
@ -35,6 +34,7 @@
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
grpc_core::ArenaPromise<absl::StatusOr<grpc_core::ClientMetadataHandle>>

@ -33,7 +33,7 @@
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
class grpc_google_iam_credentials : public grpc_call_credentials {
public:

@ -24,7 +24,6 @@
#include <stdlib.h>
#include <map>
#include <memory>
#include <string>
#include <utility>
@ -43,6 +42,7 @@
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/credentials/call_creds_util.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/uri/uri_parser.h"

@ -43,7 +43,7 @@
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/credentials/jwt/json_token.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
class grpc_service_account_jwt_access_credentials
: public grpc_call_credentials {

@ -58,6 +58,7 @@
#include "src/core/lib/promise/promise.h"
#include "src/core/lib/security/util/json_util.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/uri/uri_parser.h"

@ -48,7 +48,7 @@
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/uri/uri_parser.h"
// Constants.

@ -21,7 +21,6 @@
#include "src/core/lib/security/credentials/plugin/plugin_credentials.h"
#include <atomic>
#include <memory>
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
@ -38,6 +37,7 @@
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/validate_metadata.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
grpc_core::TraceFlag grpc_plugin_credentials_trace(false, "plugin_credentials");

@ -46,7 +46,7 @@
#include "src/core/lib/security/credentials/call_creds_util.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/call_fragments.h"
extern grpc_core::TraceFlag grpc_plugin_credentials_trace;

@ -21,7 +21,6 @@
#include <string.h>
#include <functional>
#include <memory>
#include <type_traits> // IWYU pragma: keep
#include <utility>
@ -53,6 +52,7 @@
#include "src/core/lib/security/security_connector/security_connector.h"
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"

@ -27,7 +27,6 @@
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <memory>
#include <new>
#include <string>
#include <utility>
@ -95,6 +94,7 @@
#include "src/core/lib/surface/completion_queue.h"
#include "src/core/lib/surface/server.h"
#include "src/core/lib/surface/validate_metadata.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/error_utils.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
@ -1945,14 +1945,17 @@ class PromiseBasedCall : public Call, public Activity, public Wakeable {
public promise_detail::Context<Arena>,
public promise_detail::Context<grpc_call_context_element>,
public promise_detail::Context<CallContext>,
public promise_detail::Context<CallFinalization> {
public promise_detail::Context<CallFinalization>,
public promise_detail::Context<FragmentAllocator> {
public:
explicit ScopedContext(PromiseBasedCall* call)
: ScopedActivity(call),
promise_detail::Context<Arena>(call->arena()),
promise_detail::Context<grpc_call_context_element>(call->context_),
promise_detail::Context<CallContext>(&call->call_context_),
promise_detail::Context<CallFinalization>(&call->finalization_) {}
promise_detail::Context<CallFinalization>(&call->finalization_),
promise_detail::Context<FragmentAllocator>(
&call->fragment_allocator_) {}
};
class Completion {
@ -2175,6 +2178,7 @@ class PromiseBasedCall : public Call, public Activity, public Wakeable {
/* Contexts for various subsystems (security, tracing, ...). */
grpc_call_context_element context_[GRPC_CONTEXT_COUNT] = {};
grpc_completion_queue* cq_ ABSL_GUARDED_BY(mu_);
FragmentAllocator fragment_allocator_ ABSL_GUARDED_BY(mu_);
NonOwningWakable* non_owning_wakeable_ ABSL_GUARDED_BY(mu_) = nullptr;
CompletionInfo completion_info_[6];
grpc_call_stats final_stats_{};
@ -2368,7 +2372,7 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
global_stats().IncrementClientCallsCreated();
ScopedContext context(this);
send_initial_metadata_ =
GetContext<Arena>()->MakePooled<ClientMetadata>(GetContext<Arena>());
GetContext<FragmentAllocator>()->MakeClientMetadata();
send_initial_metadata_->Set(HttpPathMetadata(), std::move(*args->path));
if (args->authority.has_value()) {
send_initial_metadata_->Set(HttpAuthorityMetadata(),
@ -2397,7 +2401,7 @@ class ClientPromiseBasedCall final : public PromiseBasedCall {
void Orphan() override {
MutexLock lock(mu());
ScopedContext ctx(this);
if (!completed_) Finish(ServerMetadataFromStatus(absl::CancelledError()));
if (!completed_) Finish(ServerMetadataHandle(absl::CancelledError()));
}
bool is_trailers_only() const override {
MutexLock lock(mu());
@ -2481,7 +2485,7 @@ void ClientPromiseBasedCall::StartPromise(
void ClientPromiseBasedCall::CancelWithError(grpc_error_handle error) {
MutexLock lock(mu());
ScopedContext context(this);
Finish(ServerMetadataFromStatus(grpc_error_to_absl_status(error)));
Finish(ServerMetadataHandle(grpc_error_to_absl_status(error)));
}
grpc_call_error ClientPromiseBasedCall::ValidateBatch(const grpc_op* ops,
@ -2564,8 +2568,8 @@ void ClientPromiseBasedCall::CommitBatch(const grpc_op* ops, size_t nops,
&op.data.send_message.send_message->data.raw.slice_buffer,
send.c_slice_buffer());
outstanding_send_.emplace(client_to_server_messages_.sender.Push(
GetContext<Arena>()->MakePooled<Message>(std::move(send),
op.flags)));
GetContext<FragmentAllocator>()->MakeMessage(std::move(send),
op.flags)));
} else {
FailCompletion(completion);
}
@ -2677,7 +2681,7 @@ void ClientPromiseBasedCall::UpdateOnce() {
outstanding_send_.reset();
if (!*result) {
FailCompletion(send_message_completion_);
Finish(ServerMetadataFromStatus(absl::Status(
Finish(ServerMetadataHandle(absl::Status(
absl::StatusCode::kInternal, "Failed to send message to server")));
}
}

@ -35,6 +35,7 @@
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/promise/activity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"

@ -46,6 +46,7 @@
#include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/transport.h"
@ -77,7 +78,7 @@ ArenaPromise<ServerMetadataHandle> LameClientFilter::MakeCallPromise(
// TODO(ctiller): remove if check once promise_based_filter is removed (Close
// is still needed)
if (args.incoming_messages != nullptr) args.incoming_messages->Close();
return Immediate(ServerMetadataFromStatus(error_));
return Immediate(ServerMetadataHandle(error_));
}
bool LameClientFilter::GetChannelInfo(const grpc_channel_info*) { return true; }

@ -35,6 +35,7 @@
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/transport.h"

@ -0,0 +1,45 @@
// Copyright 2022 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/transport/call_fragments.h"
namespace grpc_core {
FragmentAllocator::Node* FragmentAllocator::AllocateNode() {
if (free_list_ != nullptr) {
Node* node = free_list_;
free_list_ = free_list_->next_free;
return node;
}
return static_cast<Node*>(GetContext<Arena>()->Alloc(sizeof(Node)));
}
void FragmentAllocator::FreeNode(Node* node) {
node->next_free = free_list_;
free_list_ = node;
}
void FragmentAllocator::Delete(grpc_metadata_batch* p) {
p->~grpc_metadata_batch();
FreeNode(reinterpret_cast<Node*>(p));
}
void FragmentAllocator::Delete(Message* m) {
m->~Message();
FreeNode(reinterpret_cast<Node*>(m));
}
} // namespace grpc_core

@ -0,0 +1,232 @@
// Copyright 2022 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_LIB_TRANSPORT_CALL_FRAGMENTS_H
#define GRPC_CORE_LIB_TRANSPORT_CALL_FRAGMENTS_H
#include <grpc/support/port_platform.h>
#include <stdint.h>
#include <new>
#include <utility>
#include "absl/status/status.h"
#include "absl/types/optional.h"
#include <grpc/status.h>
#include "src/core/lib/promise/context.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/metadata_batch.h"
namespace grpc_core {
// TODO(ctiller): eliminate once MetadataHandle is constructable directly.
namespace promise_filter_detail {
class BaseCallData;
} // namespace promise_filter_detail
class FragmentAllocator;
// Small owned "handle" type to ensure one accessor at a time to metadata.
// The focus here is to get promises to use the syntax we'd like - we'll
// probably substitute some other smart pointer later.
template <typename T>
class FragmentHandle {
public:
FragmentHandle() = default;
FragmentHandle(const FragmentHandle&) = delete;
FragmentHandle& operator=(const FragmentHandle&) = delete;
FragmentHandle(FragmentHandle&& other) noexcept
: handle_(other.handle_),
allocated_by_allocator_(other.allocated_by_allocator_) {
other.handle_ = nullptr;
other.allocated_by_allocator_ = false;
}
FragmentHandle& operator=(FragmentHandle&& other) noexcept {
DestroyHandle();
handle_ = other.handle_;
allocated_by_allocator_ = other.allocated_by_allocator_;
other.handle_ = nullptr;
other.allocated_by_allocator_ = false;
return *this;
}
explicit FragmentHandle(const absl::Status& status);
~FragmentHandle() { DestroyHandle(); }
T* operator->() const { return handle_; }
bool has_value() const { return handle_ != nullptr; }
T* get() const { return handle_; }
void reset() { *this = FragmentHandle(); }
static FragmentHandle TestOnlyWrap(T* p) { return FragmentHandle(p, false); }
private:
// We restrict access to construction from a pointer to limit the number of
// cases that need dealing with as this code evolves.
friend class promise_filter_detail::BaseCallData;
friend class FragmentAllocator;
explicit FragmentHandle(T* handle, bool allocated_by_allocator)
: handle_(handle), allocated_by_allocator_(allocated_by_allocator) {}
void DestroyHandle();
T* Unwrap() {
T* result = handle_;
handle_ = nullptr;
return result;
}
T* handle_ = nullptr;
// TODO(ctiller): remove this once promise_based_filter goes away.
// This bit determines whether the pointer is allocated by a metadata
// allocator or some other system. If it's held by a metadata allocator, we'll
// release it back when we're done with it.
bool allocated_by_allocator_ = false;
};
// Server metadata type
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
using ServerMetadata = grpc_metadata_batch;
using ServerMetadataHandle = FragmentHandle<ServerMetadata>;
// Client initial metadata type
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
using ClientMetadata = grpc_metadata_batch;
using ClientMetadataHandle = FragmentHandle<ClientMetadata>;
class Message {
public:
Message() = default;
~Message() = default;
Message(SliceBuffer payload, uint32_t flags)
: payload_(std::move(payload)), flags_(flags) {}
Message(const Message&) = delete;
Message& operator=(const Message&) = delete;
uint32_t flags() const { return flags_; }
SliceBuffer* payload() { return &payload_; }
const SliceBuffer* payload() const { return &payload_; }
private:
SliceBuffer payload_;
uint32_t flags_ = 0;
};
using MessageHandle = FragmentHandle<Message>;
// Ok/not-ok check for trailing metadata, so that it can be used as result types
// for TrySeq.
inline bool IsStatusOk(const ServerMetadataHandle& m) {
return m->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
GRPC_STATUS_OK;
}
// Within a call arena we need metadata at least four times - (client,server) x
// (initial,trailing), and possibly more for early returning promises.
// Since we often don't need these *simultaneously*, we can save memory by
// allocating/releasing them.
// We'd still like the memory to be part of the arena though, so this type
// creates a small free list of metadata objects and a central (call context)
// based place to create/destroy them.
class FragmentAllocator {
public:
FragmentAllocator() = default;
~FragmentAllocator() = default;
FragmentAllocator(const FragmentAllocator&) = delete;
FragmentAllocator& operator=(const FragmentAllocator&) = delete;
ClientMetadataHandle MakeClientMetadata() {
auto* node = AllocateNode();
// TODO(ctiller): once we finish the promise transition, have metadata map
// know about arena contexts and allocate directly from there.
// (we could do so before, but there's enough places where we don't have a
// promise context up that it's too much whackamole)
new (&node->batch) ClientMetadata(GetContext<Arena>());
return ClientMetadataHandle(&node->batch, true);
}
ServerMetadataHandle MakeServerMetadata() { return MakeClientMetadata(); }
template <typename... Args>
MessageHandle MakeMessage(Args&&... args) {
auto* node = AllocateNode();
new (&node->message) Message(std::forward<Args>(args)...);
return MessageHandle(&node->message, true);
}
private:
union Node {
Node* next_free;
grpc_metadata_batch batch;
Message message;
};
template <typename T>
friend class FragmentHandle;
void Delete(grpc_metadata_batch* p);
void Delete(Message* m);
Node* AllocateNode();
void FreeNode(Node* node);
Node* free_list_ = nullptr;
};
template <>
struct ContextType<FragmentAllocator> {};
template <typename T>
FragmentHandle<T>::FragmentHandle(const absl::Status& status) {
// TODO(ctiller): currently we guarantee that MetadataAllocator is only
// present for promise based calls, and if we're using promise_based_filter
// it's not present. If we're in a promise based call, the correct thing is to
// use the metadata allocator to track the memory we need. If we're not, we
// need to do the hacky thing promise_based_filter does.
// This all goes away when promise_based_filter goes away, and this code will
// just assume there's an allocator present and move forward.
if (HasContext<FragmentAllocator>()) {
handle_ = nullptr;
allocated_by_allocator_ = false;
*this = GetContext<FragmentAllocator>()->MakeServerMetadata();
} else {
handle_ = GetContext<Arena>()->New<T>(GetContext<Arena>());
allocated_by_allocator_ = false;
}
handle_->Set(GrpcStatusMetadata(),
static_cast<grpc_status_code>(status.code()));
if (status.ok()) return;
handle_->Set(GrpcMessageMetadata(),
Slice::FromCopiedString(status.message()));
}
template <typename T>
void FragmentHandle<T>::DestroyHandle() {
if (allocated_by_allocator_) {
GetContext<FragmentAllocator>()->Delete(handle_);
}
}
} // namespace grpc_core
#endif // GRPC_CORE_LIB_TRANSPORT_CALL_FRAGMENTS_H

@ -32,8 +32,6 @@
#include "src/core/lib/event_engine/default_event_engine.h"
#include "src/core/lib/gpr/alloc.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/promise/context.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/transport_impl.h"
grpc_core::DebugOnlyTraceFlag grpc_trace_stream_refcount(false,
@ -269,17 +267,3 @@ grpc_transport_stream_op_batch* grpc_make_transport_stream_op(
op->op.on_complete = &op->outer_on_complete;
return &op->op;
}
namespace grpc_core {
ServerMetadataHandle ServerMetadataFromStatus(const absl::Status& status) {
auto hdl =
GetContext<Arena>()->MakePooled<ServerMetadata>(GetContext<Arena>());
hdl->Set(GrpcStatusMetadata(), static_cast<grpc_status_code>(status.code()));
if (!status.ok()) {
hdl->Set(GrpcMessageMetadata(), Slice::FromCopiedString(status.message()));
}
return hdl;
}
} // namespace grpc_core

@ -27,9 +27,7 @@
#include <functional>
#include <string>
#include <utility>
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
@ -51,11 +49,11 @@
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/promise/detail/status.h"
#include "src/core/lib/promise/latch.h"
#include "src/core/lib/promise/pipe.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/slice/slice_buffer.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport_fwd.h"
@ -83,59 +81,6 @@ struct grpc_transport_stream_op_batch_payload;
namespace grpc_core {
// Server metadata type
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
using ServerMetadata = grpc_metadata_batch;
using ServerMetadataHandle = Arena::PoolPtr<ServerMetadata>;
// Client initial metadata type
// TODO(ctiller): This should be a bespoke instance of MetadataMap<>
using ClientMetadata = grpc_metadata_batch;
using ClientMetadataHandle = Arena::PoolPtr<ClientMetadata>;
class Message {
public:
Message() = default;
~Message() = default;
Message(SliceBuffer payload, uint32_t flags)
: payload_(std::move(payload)), flags_(flags) {}
Message(const Message&) = delete;
Message& operator=(const Message&) = delete;
uint32_t flags() const { return flags_; }
SliceBuffer* payload() { return &payload_; }
const SliceBuffer* payload() const { return &payload_; }
private:
SliceBuffer payload_;
uint32_t flags_ = 0;
};
using MessageHandle = Arena::PoolPtr<Message>;
// Ok/not-ok check for trailing metadata, so that it can be used as result types
// for TrySeq.
inline bool IsStatusOk(const ServerMetadataHandle& m) {
return m->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) ==
GRPC_STATUS_OK;
}
ServerMetadataHandle ServerMetadataFromStatus(const absl::Status& status);
template <>
struct StatusCastImpl<ServerMetadataHandle, absl::Status> {
static ServerMetadataHandle Cast(const absl::Status& m) {
return ServerMetadataFromStatus(m);
}
};
template <>
struct StatusCastImpl<ServerMetadataHandle, const absl::Status&> {
static ServerMetadataHandle Cast(const absl::Status& m) {
return ServerMetadataFromStatus(m);
}
};
struct CallArgs {
// Initial metadata from the client to the server.
// During promise setup this can be manipulated by filters (and then

@ -30,6 +30,7 @@
#include "src/core/lib/iomgr/iomgr_fwd.h"
#include "src/core/lib/promise/arena_promise.h"
#include "src/core/lib/resource_quota/arena.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/transport.h"
#include "src/core/lib/transport/transport_fwd.h"

@ -709,6 +709,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/surface/validate_metadata.cc',
'src/core/lib/surface/version.cc',
'src/core/lib/transport/bdp_estimator.cc',
'src/core/lib/transport/call_fragments.cc',
'src/core/lib/transport/connectivity_state.cc',
'src/core/lib/transport/error_utils.cc',
'src/core/lib/transport/handshaker.cc',

@ -49,6 +49,7 @@
#include "src/core/lib/security/security_connector/security_connector.h"
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
#include "test/core/promise/test_context.h"
@ -153,14 +154,13 @@ TEST_F(ClientAuthFilterTest, CallCredsFails) {
TestContext<Arena> context(arena_.get());
TestContext<grpc_call_context_element> promise_call_context(call_context_);
auto promise = filter->MakeCallPromise(
CallArgs{ClientMetadataHandle(&initial_metadata_batch_,
Arena::PooledDeleter(nullptr)),
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch_),
nullptr, nullptr, nullptr},
[&](CallArgs /*call_args*/) {
return ArenaPromise<ServerMetadataHandle>(
[&]() -> Poll<ServerMetadataHandle> {
return ServerMetadataHandle(&trailing_metadata_batch_,
Arena::PooledDeleter(nullptr));
return ServerMetadataHandle::TestOnlyWrap(
&trailing_metadata_batch_);
});
});
auto result = promise();
@ -174,6 +174,7 @@ TEST_F(ClientAuthFilterTest, CallCredsFails) {
(*server_metadata)->get_pointer(GrpcMessageMetadata());
ASSERT_TRUE(message_md != nullptr);
EXPECT_EQ(message_md->as_string_view(), "access denied");
(*server_metadata)->~ServerMetadata();
}
TEST_F(ClientAuthFilterTest, RewritesInvalidStatusFromCallCreds) {
@ -183,14 +184,13 @@ TEST_F(ClientAuthFilterTest, RewritesInvalidStatusFromCallCreds) {
TestContext<Arena> context(arena_.get());
TestContext<grpc_call_context_element> promise_call_context(call_context_);
auto promise = filter->MakeCallPromise(
CallArgs{ClientMetadataHandle(&initial_metadata_batch_,
Arena::PooledDeleter(nullptr)),
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch_),
nullptr, nullptr, nullptr},
[&](CallArgs /*call_args*/) {
return ArenaPromise<ServerMetadataHandle>(
[&]() -> Poll<ServerMetadataHandle> {
return ServerMetadataHandle(&trailing_metadata_batch_,
Arena::PooledDeleter(nullptr));
return ServerMetadataHandle::TestOnlyWrap(
&trailing_metadata_batch_);
});
});
auto result = promise();
@ -206,6 +206,7 @@ TEST_F(ClientAuthFilterTest, RewritesInvalidStatusFromCallCreds) {
EXPECT_EQ(message_md->as_string_view(),
"Illegal status code from call credentials; original status: "
"ABORTED: nope");
(*server_metadata)->~ServerMetadata();
}
} // namespace

@ -71,8 +71,7 @@ TEST(ClientAuthorityFilterTest, PromiseCompletesImmediatelyAndSetsAuthority) {
// TODO(ctiller): use Activity here, once it's ready.
TestContext<Arena> context(arena.get());
auto promise = filter.MakeCallPromise(
CallArgs{ClientMetadataHandle(&initial_metadata_batch,
Arena::PooledDeleter(nullptr)),
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch),
nullptr, nullptr, nullptr},
[&](CallArgs call_args) {
EXPECT_EQ(call_args.client_initial_metadata
@ -82,8 +81,8 @@ TEST(ClientAuthorityFilterTest, PromiseCompletesImmediatelyAndSetsAuthority) {
seen = true;
return ArenaPromise<ServerMetadataHandle>(
[&]() -> Poll<ServerMetadataHandle> {
return ServerMetadataHandle(&trailing_metadata_batch,
Arena::PooledDeleter(nullptr));
return ServerMetadataHandle::TestOnlyWrap(
&trailing_metadata_batch);
});
});
auto result = promise();
@ -104,8 +103,7 @@ TEST(ClientAuthorityFilterTest,
// TODO(ctiller): use Activity here, once it's ready.
TestContext<Arena> context(arena.get());
auto promise = filter.MakeCallPromise(
CallArgs{ClientMetadataHandle(&initial_metadata_batch,
Arena::PooledDeleter(nullptr)),
CallArgs{ClientMetadataHandle::TestOnlyWrap(&initial_metadata_batch),
nullptr, nullptr, nullptr},
[&](CallArgs call_args) {
EXPECT_EQ(call_args.client_initial_metadata
@ -115,8 +113,8 @@ TEST(ClientAuthorityFilterTest,
seen = true;
return ArenaPromise<ServerMetadataHandle>(
[&]() -> Poll<ServerMetadataHandle> {
return ServerMetadataHandle(&trailing_metadata_batch,
Arena::PooledDeleter(nullptr));
return ServerMetadataHandle::TestOnlyWrap(
&trailing_metadata_batch);
});
});
auto result = promise();

@ -79,6 +79,7 @@
#include "src/core/lib/security/transport/auth_filters.h"
#include "src/core/lib/slice/slice.h"
#include "src/core/lib/surface/channel_stack_type.h"
#include "src/core/lib/transport/call_fragments.h"
#include "src/core/lib/transport/handshaker.h"
#include "src/core/lib/transport/metadata_batch.h"
#include "src/core/lib/transport/transport.h"
@ -585,7 +586,7 @@ class MainLoop {
};
template <typename R>
absl::optional<Arena::PoolPtr<R>> LoadMetadata(
absl::optional<FragmentHandle<R>> LoadMetadata(
const filter_fuzzer::Metadata& metadata, std::unique_ptr<R>* out) {
if (*out != nullptr) return absl::nullopt;
*out = std::make_unique<R>(arena_.get());
@ -593,7 +594,7 @@ class MainLoop {
(*out)->Append(md.key(), Slice::FromCopiedString(md.value()),
[](absl::string_view, const Slice&) {});
}
return Arena::PoolPtr<R>(out->get(), Arena::PooledDeleter(nullptr));
return FragmentHandle<R>::TestOnlyWrap(out->get());
}
void Step() {
@ -607,8 +608,8 @@ class MainLoop {
Poll<ServerMetadataHandle> CheckCompletion() {
if (server_trailing_metadata_ != nullptr) {
return ServerMetadataHandle(server_trailing_metadata_.get(),
Arena::PooledDeleter(nullptr));
return ServerMetadataHandle::TestOnlyWrap(
server_trailing_metadata_.get());
}
server_trailing_metadata_waker_ = MakeOwningWaker();
return Pending{};

@ -39,12 +39,12 @@
#include "src/core/lib/resource_quota/resource_quota.h"
#include "test/core/util/test_config.h"
namespace grpc_core {
using grpc_core::Arena;
using grpc_core::ExecCtx;
namespace {
auto* g_memory_allocator = new MemoryAllocator(
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test"));
}
static auto* g_memory_allocator = new grpc_core::MemoryAllocator(
grpc_core::ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator(
"test"));
TEST(ArenaTest, NoOp) {
ExecCtx exec_ctx;
@ -116,10 +116,10 @@ TEST(ArenaTest, ConcurrentAlloc) {
gpr_event_init(&args.ev_start);
args.arena = Arena::Create(1024, g_memory_allocator);
Thread thds[CONCURRENT_TEST_THREADS];
grpc_core::Thread thds[CONCURRENT_TEST_THREADS];
for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
thds[i] = Thread(
thds[i] = grpc_core::Thread(
"grpc_concurrent_test",
[](void* arg) {
concurrent_test_args* a = static_cast<concurrent_test_args*>(arg);
@ -146,10 +146,10 @@ TEST(ArenaTest, ConcurrentManagedNew) {
gpr_event_init(&args.ev_start);
args.arena = Arena::Create(1024, g_memory_allocator);
Thread thds[CONCURRENT_TEST_THREADS];
grpc_core::Thread thds[CONCURRENT_TEST_THREADS];
for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
thds[i] = Thread(
thds[i] = grpc_core::Thread(
"grpc_concurrent_test",
[](void* arg) {
concurrent_test_args* a = static_cast<concurrent_test_args*>(arg);
@ -172,33 +172,6 @@ TEST(ArenaTest, ConcurrentManagedNew) {
args.arena->Destroy();
}
TEST(ArenaTest, PooledObjectsArePooled) {
struct TestObj {
char a[100];
};
auto arena = MakeScopedArena(1024, g_memory_allocator);
auto obj = arena->MakePooled<TestObj>();
void* p = obj.get();
obj.reset();
obj = arena->MakePooled<TestObj>();
EXPECT_EQ(p, obj.get());
}
TEST(ArenaTest, CreateManyObjects) {
struct TestObj {
char a[100];
};
auto arena = MakeScopedArena(1024, g_memory_allocator);
std::vector<Arena::PoolPtr<TestObj>> objs;
objs.reserve(1000);
for (int i = 0; i < 1000; i++) {
objs.emplace_back(arena->MakePooled<TestObj>());
}
}
} // namespace grpc_core
int main(int argc, char* argv[]) {
grpc::testing::TestEnvironment give_me_a_name(&argc, argv);
::testing::InitGoogleTest(&argc, argv);

@ -463,16 +463,15 @@ class RequestMetadataState : public RefCounted<RequestMetadataState> {
md_.Set(HttpPathMetadata(), Slice::FromStaticString(path));
activity_ = MakeActivity(
[this, creds] {
return Seq(
creds->GetRequestMetadata(
ClientMetadataHandle(&md_, Arena::PooledDeleter(nullptr)),
&get_request_metadata_args_),
[this](absl::StatusOr<ClientMetadataHandle> metadata) {
if (metadata.ok()) {
GPR_ASSERT(metadata->get() == &md_);
}
return metadata.status();
});
return Seq(creds->GetRequestMetadata(
ClientMetadataHandle::TestOnlyWrap(&md_),
&get_request_metadata_args_),
[this](absl::StatusOr<ClientMetadataHandle> metadata) {
if (metadata.ok()) {
GPR_ASSERT(metadata->get() == &md_);
}
return metadata.status();
});
},
ExecCtxWakeupScheduler(),
[self](absl::Status status) mutable {

@ -59,9 +59,8 @@ char* grpc_test_fetch_oauth2_token_with_credentials(
[creds, &initial_metadata, &get_request_metadata_args]() {
return grpc_core::Map(
creds->GetRequestMetadata(
grpc_core::ClientMetadataHandle(
&initial_metadata,
grpc_core::Arena::PooledDeleter(nullptr)),
grpc_core::ClientMetadataHandle::TestOnlyWrap(
&initial_metadata),
&get_request_metadata_args),
[](const absl::StatusOr<grpc_core::ClientMetadataHandle>& s) {
return s.status();

@ -65,6 +65,21 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "call_fragments_test",
srcs = ["call_fragments_test.cc"],
external_deps = [
"gtest",
],
language = "C++",
deps = [
"//:gpr",
"//:grpc",
"//test/core/promise:test_context",
"//test/core/util:grpc_test_util",
],
)
grpc_cc_test(
name = "metadata_map_test",
srcs = ["metadata_map_test.cc"],

@ -0,0 +1,96 @@
//
// Copyright 2021 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 "src/core/lib/transport/call_fragments.h"
#include <algorithm>
#include <memory>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <grpc/event_engine/memory_allocator.h>
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/lib/resource_quota/memory_quota.h"
#include "src/core/lib/resource_quota/resource_quota.h"
#include "test/core/promise/test_context.h"
#include "test/core/util/test_config.h"
using testing::Each;
namespace grpc_core {
namespace testing {
class CallFragmentsTest : public ::testing::Test {
protected:
CallFragmentsTest() {}
~CallFragmentsTest() override {}
private:
MemoryAllocator memory_allocator_ =
ResourceQuota::Default()->memory_quota()->CreateMemoryAllocator("test");
ScopedArenaPtr arena_ = MakeScopedArena(4096, &memory_allocator_);
FragmentAllocator fragment_allocator_;
TestContext<Arena> arena_context_{arena_.get()};
TestContext<FragmentAllocator> fragment_allocator_context_{
&fragment_allocator_};
};
// Ensure test fixture can init/destroy successfully.
TEST_F(CallFragmentsTest, Nothing) {}
// Ensure we can create/destroy some client metadata.
TEST_F(CallFragmentsTest, ClientMetadata) {
GetContext<FragmentAllocator>()->MakeClientMetadata();
}
// Ensure we can create/destroy some server metadata.
TEST_F(CallFragmentsTest, ServerMetadata) {
GetContext<FragmentAllocator>()->MakeServerMetadata();
}
// Ensure repeated allocation/deallocations reuse memory.
TEST_F(CallFragmentsTest, RepeatedAllocationsReuseMemory) {
void* p = GetContext<FragmentAllocator>()->MakeClientMetadata().get();
void* q = GetContext<FragmentAllocator>()->MakeClientMetadata().get();
EXPECT_EQ(p, q);
}
// Ensure repeated allocation reinitializes.
TEST_F(CallFragmentsTest, RepeatedAllocationsReinitialize) {
std::vector<void*> addresses;
for (int i = 0; i < 4; i++) {
ClientMetadataHandle metadata =
GetContext<FragmentAllocator>()->MakeClientMetadata();
EXPECT_EQ(metadata->get_pointer(HttpPathMetadata()), nullptr);
metadata->Set(HttpPathMetadata(), Slice::FromCopiedString("/"));
EXPECT_EQ(metadata->get_pointer(HttpPathMetadata())->as_string_view(), "/");
addresses.push_back(metadata.get());
}
EXPECT_THAT(addresses, Each(addresses[0]));
}
} // namespace testing
} // namespace grpc_core
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(&argc, argv);
return RUN_ALL_TESTS();
};

@ -2481,6 +2481,8 @@ src/core/lib/surface/validate_metadata.h \
src/core/lib/surface/version.cc \
src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/bdp_estimator.h \
src/core/lib/transport/call_fragments.cc \
src/core/lib/transport/call_fragments.h \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/connectivity_state.h \
src/core/lib/transport/error_utils.cc \

@ -2274,6 +2274,8 @@ src/core/lib/surface/version.cc \
src/core/lib/transport/README.md \
src/core/lib/transport/bdp_estimator.cc \
src/core/lib/transport/bdp_estimator.h \
src/core/lib/transport/call_fragments.cc \
src/core/lib/transport/call_fragments.h \
src/core/lib/transport/connectivity_state.cc \
src/core/lib/transport/connectivity_state.h \
src/core/lib/transport/error_utils.cc \

@ -1415,6 +1415,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "call_fragments_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save