Merge remote-tracking branch 'upstream/master' into better-ares-error-code

pull/37371/head
yijiem 4 months ago
commit 6f367d1051
  1. 1
      BUILD
  2. 78
      CMakeLists.txt
  3. 1
      Makefile
  4. 3
      Package.swift
  5. 4
      bazel/experiments.bzl
  6. 48
      build_autogenerated.yaml
  7. 1
      config.m4
  8. 1
      config.w32
  9. 99
      examples/cpp/otel/codelab/BUILD
  10. 87
      examples/cpp/otel/codelab/CMakeLists.txt
  11. 138
      examples/cpp/otel/codelab/greeter_callback_client.cc
  12. 158
      examples/cpp/otel/codelab/greeter_callback_client_solution.cc
  13. 112
      examples/cpp/otel/codelab/greeter_callback_server.cc
  14. 127
      examples/cpp/otel/codelab/greeter_callback_server_solution.cc
  15. 70
      examples/cpp/otel/codelab/util.cc
  16. 31
      examples/cpp/otel/codelab/util.h
  17. 3
      examples/cpp/route_guide/CMakeLists.txt
  18. 4
      gRPC-C++.podspec
  19. 5
      gRPC-Core.podspec
  20. 3
      grpc.gemspec
  21. 3
      package.xml
  22. 32
      src/core/BUILD
  23. 2
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  24. 3
      src/core/ext/transport/chttp2/transport/internal.h
  25. 45
      src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
  26. 67
      src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h
  27. 14
      src/core/ext/transport/chttp2/transport/parsing.cc
  28. 4
      src/core/ext/transport/chttp2/transport/writing.cc
  29. 18
      src/core/lib/experiments/experiments.cc
  30. 8
      src/core/lib/experiments/experiments.h
  31. 6
      src/core/lib/experiments/experiments.yaml
  32. 28
      src/core/lib/gprpp/table.h
  33. 6
      src/core/lib/promise/party.cc
  34. 41
      src/core/lib/transport/metadata_batch.h
  35. 14
      src/core/util/latent_see.cc
  36. 8
      src/core/util/latent_see.h
  37. 123
      src/core/util/ring_buffer.h
  38. 24
      src/core/util/useful.h
  39. 1
      src/python/grpcio/grpc_core_dependencies.py
  40. 10
      test/core/transport/chttp2/BUILD
  41. 48
      test/core/transport/chttp2/max_concurrent_streams_policy_test.cc
  42. 77
      test/core/transport/metadata_map_test.cc
  43. 13
      test/core/util/BUILD
  44. 89
      test/core/util/ring_buffer_test.cc
  45. 49
      test/core/util/useful_test.cc
  46. 3
      tools/doxygen/Doxyfile.c++.internal
  47. 3
      tools/doxygen/Doxyfile.core.internal
  48. 48
      tools/run_tests/generated/tests.json

@ -4829,7 +4829,6 @@ grpc_cc_library(
"//src/core:iomgr_fwd",
"//src/core:iomgr_port",
"//src/core:match",
"//src/core:max_concurrent_streams_policy",
"//src/core:memory_quota",
"//src/core:metadata_batch",
"//src/core:metadata_info",

78
CMakeLists.txt generated

@ -1261,7 +1261,6 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx map_pipe_test)
add_dependencies(buildtests_cxx match_test)
add_dependencies(buildtests_cxx matchers_test)
add_dependencies(buildtests_cxx max_concurrent_streams_policy_test)
add_dependencies(buildtests_cxx max_concurrent_streams_test)
add_dependencies(buildtests_cxx max_connection_age_test)
add_dependencies(buildtests_cxx max_connection_idle_test)
@ -1412,6 +1411,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx retry_transparent_not_sent_on_wire_test)
add_dependencies(buildtests_cxx retry_unref_before_finish_test)
add_dependencies(buildtests_cxx retry_unref_before_recv_test)
add_dependencies(buildtests_cxx ring_buffer_test)
add_dependencies(buildtests_cxx ring_hash_test)
add_dependencies(buildtests_cxx rls_end2end_test)
add_dependencies(buildtests_cxx rls_lb_config_parser_test)
@ -1946,7 +1946,6 @@ add_library(grpc
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
src/core/ext/transport/chttp2/transport/http2_settings.cc
src/core/ext/transport/chttp2/transport/huffsyms.cc
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
src/core/ext/transport/chttp2/transport/parsing.cc
src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc
src/core/ext/transport/chttp2/transport/ping_callbacks.cc
@ -3043,7 +3042,6 @@ add_library(grpc_unsecure
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
src/core/ext/transport/chttp2/transport/http2_settings.cc
src/core/ext/transport/chttp2/transport/huffsyms.cc
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
src/core/ext/transport/chttp2/transport/parsing.cc
src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc
src/core/ext/transport/chttp2/transport/ping_callbacks.cc
@ -20369,48 +20367,6 @@ target_link_libraries(matchers_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(max_concurrent_streams_policy_test
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
test/core/transport/chttp2/max_concurrent_streams_policy_test.cc
)
if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS)
target_compile_definitions(max_concurrent_streams_policy_test
PRIVATE
"GPR_DLL_IMPORTS"
)
endif()
endif()
target_compile_features(max_concurrent_streams_policy_test PUBLIC cxx_std_14)
target_include_directories(max_concurrent_streams_policy_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(max_concurrent_streams_policy_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
gpr
)
endif()
if(gRPC_BUILD_TESTS)
@ -27274,6 +27230,38 @@ target_link_libraries(retry_unref_before_recv_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(ring_buffer_test
test/core/util/ring_buffer_test.cc
)
target_compile_features(ring_buffer_test PUBLIC cxx_std_14)
target_include_directories(ring_buffer_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(ring_buffer_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
)
endif()
if(gRPC_BUILD_TESTS)

1
Makefile generated

@ -726,7 +726,6 @@ LIBGRPC_SRC = \
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc \
src/core/ext/transport/chttp2/transport/ping_callbacks.cc \

3
Package.swift generated

@ -244,8 +244,6 @@ let package = Package(
"src/core/ext/transport/chttp2/transport/huffsyms.h",
"src/core/ext/transport/chttp2/transport/internal.h",
"src/core/ext/transport/chttp2/transport/legacy_frame.h",
"src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc",
"src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h",
"src/core/ext/transport/chttp2/transport/parsing.cc",
"src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc",
"src/core/ext/transport/chttp2/transport/ping_abuse_policy.h",
@ -1942,6 +1940,7 @@ let package = Package(
"src/core/util/posix/sync.cc",
"src/core/util/posix/time.cc",
"src/core/util/posix/tmpfile.cc",
"src/core/util/ring_buffer.h",
"src/core/util/spinlock.h",
"src/core/util/string.cc",
"src/core/util/string.h",

@ -31,7 +31,6 @@ EXPERIMENT_ENABLES = {
"peer_state_based_framing": "peer_state_based_framing",
"pick_first_new": "pick_first_new",
"promise_based_inproc_transport": "promise_based_inproc_transport",
"rstpit": "rstpit",
"schedule_cancellation_over_write": "schedule_cancellation_over_write",
"server_privacy": "server_privacy",
"tcp_frame_size_tuning": "tcp_frame_size_tuning",
@ -60,7 +59,6 @@ EXPERIMENTS = {
"flow_control_test": [
"multiping",
"peer_state_based_framing",
"rstpit",
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
@ -108,7 +106,6 @@ EXPERIMENTS = {
"flow_control_test": [
"multiping",
"peer_state_based_framing",
"rstpit",
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],
@ -150,7 +147,6 @@ EXPERIMENTS = {
"flow_control_test": [
"multiping",
"peer_state_based_framing",
"rstpit",
"tcp_frame_size_tuning",
"tcp_rcv_lowat",
],

@ -290,7 +290,6 @@ libs:
- src/core/ext/transport/chttp2/transport/huffsyms.h
- src/core/ext/transport/chttp2/transport/internal.h
- src/core/ext/transport/chttp2/transport/legacy_frame.h
- src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h
- src/core/ext/transport/chttp2/transport/ping_abuse_policy.h
- src/core/ext/transport/chttp2/transport/ping_callbacks.h
- src/core/ext/transport/chttp2/transport/ping_rate_policy.h
@ -1218,6 +1217,7 @@ libs:
- src/core/util/json/json_util.h
- src/core/util/json/json_writer.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- src/core/util/upb_utils.h
- src/core/xds/grpc/certificate_provider_store.h
@ -1319,7 +1319,6 @@ libs:
- src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
- src/core/ext/transport/chttp2/transport/http2_settings.cc
- src/core/ext/transport/chttp2/transport/huffsyms.cc
- src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
- src/core/ext/transport/chttp2/transport/parsing.cc
- src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc
- src/core/ext/transport/chttp2/transport/ping_callbacks.cc
@ -2289,7 +2288,6 @@ libs:
- src/core/ext/transport/chttp2/transport/huffsyms.h
- src/core/ext/transport/chttp2/transport/internal.h
- src/core/ext/transport/chttp2/transport/legacy_frame.h
- src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h
- src/core/ext/transport/chttp2/transport/ping_abuse_policy.h
- src/core/ext/transport/chttp2/transport/ping_callbacks.h
- src/core/ext/transport/chttp2/transport/ping_rate_policy.h
@ -2705,6 +2703,7 @@ libs:
- src/core/util/json/json_reader.h
- src/core/util/json/json_writer.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- src/core/util/upb_utils.h
- third_party/upb/upb/generated_code_support.h
@ -2764,7 +2763,6 @@ libs:
- src/core/ext/transport/chttp2/transport/hpack_parser_table.cc
- src/core/ext/transport/chttp2/transport/http2_settings.cc
- src/core/ext/transport/chttp2/transport/huffsyms.cc
- src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
- src/core/ext/transport/chttp2/transport/parsing.cc
- src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc
- src/core/ext/transport/chttp2/transport/ping_callbacks.cc
@ -4755,6 +4753,7 @@ libs:
- src/core/util/json/json_reader.h
- src/core/util/json/json_writer.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -5484,6 +5483,7 @@ targets:
- src/core/lib/promise/seq.h
- src/core/lib/promise/wait_set.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/test_wakeup_schedulers.h
src:
- src/core/lib/debug/trace.cc
@ -6714,6 +6714,7 @@ targets:
- src/core/lib/transport/status_conversion.h
- src/core/lib/transport/timeout_encoding.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- test/core/promise/poll_matcher.h
- third_party/upb/upb/generated_code_support.h
@ -6901,6 +6902,7 @@ targets:
- src/core/lib/promise/status_flag.h
- src/core/lib/transport/call_state.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/poll_matcher.h
src:
- src/core/lib/debug/trace.cc
@ -7245,6 +7247,7 @@ targets:
- src/core/util/json/json_args.h
- src/core/util/json/json_writer.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -7898,6 +7901,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -8693,6 +8697,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -10241,6 +10246,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -10791,6 +10797,7 @@ targets:
- src/core/lib/transport/bdp_estimator.h
- src/core/lib/transport/http2_errors.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -10907,6 +10914,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- test/core/promise/test_wakeup_schedulers.h
- third_party/upb/upb/generated_code_support.h
@ -12491,6 +12499,7 @@ targets:
- src/core/lib/promise/poll.h
- src/core/lib/promise/seq.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/test_wakeup_schedulers.h
src:
- src/core/lib/debug/trace.cc
@ -12581,6 +12590,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- test/core/promise/test_context.h
- third_party/upb/upb/generated_code_support.h
@ -13053,6 +13063,7 @@ targets:
- src/core/lib/promise/poll.h
- src/core/lib/promise/seq.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/test_wakeup_schedulers.h
src:
- src/core/lib/debug/trace.cc
@ -13286,6 +13297,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- test/core/promise/test_wakeup_schedulers.h
- third_party/upb/upb/generated_code_support.h
@ -13372,18 +13384,6 @@ targets:
deps:
- gtest
- grpc_test_util
- name: max_concurrent_streams_policy_test
gtest: true
build: test
language: c++
headers:
- src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h
src:
- src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc
- test/core/transport/chttp2/max_concurrent_streams_policy_test.cc
deps:
- gtest
- gpr
- name: max_concurrent_streams_test
gtest: true
build: test
@ -13840,6 +13840,7 @@ targets:
- src/core/lib/promise/promise.h
- src/core/lib/promise/wait_set.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/poll_matcher.h
src:
- src/core/lib/debug/trace.cc
@ -14153,6 +14154,7 @@ targets:
- src/core/lib/promise/observable.h
- src/core/lib/promise/poll.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/poll_matcher.h
src:
- src/core/lib/debug/trace.cc
@ -14507,6 +14509,7 @@ targets:
- src/core/lib/slice/slice_refcount.h
- src/core/lib/slice/slice_string_helpers.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- src/core/util/spinlock.h
- third_party/upb/upb/generated_code_support.h
src:
@ -15072,6 +15075,7 @@ targets:
- src/core/lib/promise/promise_mutex.h
- src/core/lib/promise/seq.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/test_wakeup_schedulers.h
src:
- src/core/lib/debug/trace.cc
@ -18044,6 +18048,17 @@ targets:
- grpc_authorization_provider
- grpc_unsecure
- grpc_test_util
- name: ring_buffer_test
gtest: true
build: test
language: c++
headers:
- src/core/util/ring_buffer.h
src:
- test/core/util/ring_buffer_test.cc
deps:
- gtest
uses_polling: false
- name: ring_hash_test
gtest: true
build: test
@ -20861,6 +20876,7 @@ targets:
- src/core/lib/promise/poll.h
- src/core/lib/promise/wait_for_callback.h
- src/core/util/latent_see.h
- src/core/util/ring_buffer.h
- test/core/promise/test_wakeup_schedulers.h
src:
- src/core/lib/debug/trace.cc

1
config.m4 generated

@ -101,7 +101,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
src/core/ext/transport/chttp2/transport/http2_settings.cc \
src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc \
src/core/ext/transport/chttp2/transport/ping_callbacks.cc \

1
config.w32 generated

@ -66,7 +66,6 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\transport\\chttp2\\transport\\hpack_parser_table.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\http2_settings.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\huffsyms.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\max_concurrent_streams_policy.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\parsing.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\ping_abuse_policy.cc " +
"src\\core\\ext\\transport\\chttp2\\transport\\ping_callbacks.cc " +

@ -0,0 +1,99 @@
# Copyright 2023 the 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.
licenses(["notice"])
package(
default_visibility = ["//examples/cpp:__subpackages__"],
)
cc_library(
name = "util",
srcs = ["util.cc"],
hdrs = ["util.h"],
defines = ["BAZEL_BUILD"],
deps = [
"//:grpc++",
"//examples/protos:helloworld_cc_grpc",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)
cc_binary(
name = "greeter_callback_client",
srcs = ["greeter_callback_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"util",
"//:grpc++",
"//:grpcpp_otel_plugin",
"//examples/cpp/otel:util",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)
cc_binary(
name = "greeter_callback_server",
srcs = ["greeter_callback_server.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"util",
"//:grpc++",
"//:grpc++_reflection",
"//:grpcpp_otel_plugin",
"//examples/cpp/otel:util",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@com_google_absl//absl/strings:str_format",
"@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)
cc_binary(
name = "greeter_callback_client_solution",
srcs = ["greeter_callback_client_solution.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"util",
"//:grpc++",
"//:grpcpp_otel_plugin",
"//examples/cpp/otel:util",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)
cc_binary(
name = "greeter_callback_server_solution",
srcs = ["greeter_callback_server_solution.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"util",
"//:grpc++",
"//:grpc++_reflection",
"//:grpcpp_otel_plugin",
"//examples/cpp/otel:util",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@com_google_absl//absl/strings:str_format",
"@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)

@ -0,0 +1,87 @@
# Copyright 2018 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.
#
# cmake build file for C++ gRPC OpenTelemetry example.
# Assumes absl, protobuf, prometheus-cpp, opentelemetry-cpp and gRPC (with -DgRPC_BUILD_OPENTELEMETRY_PLUGIN=ON) have been installed using cmake.
# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build
# that automatically builds all the dependencies before building helloworld.
cmake_minimum_required(VERSION 3.13)
project(grpc_opentelemetry_example C CXX)
include(../../cmake/common.cmake)
# Find prometheus-cpp package
find_package(prometheus-cpp CONFIG REQUIRED)
# Find opentelemetry-cpp package
find_package(opentelemetry-cpp CONFIG REQUIRED)
# Proto file
get_filename_component(hw_proto "../../../protos/helloworld.proto" ABSOLUTE)
get_filename_component(hw_proto_path "${hw_proto}" PATH)
# Generated sources
set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc")
set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h")
set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc")
set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h")
add_custom_command(
OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}"
COMMAND ${_PROTOBUF_PROTOC}
ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"
--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"
-I "${hw_proto_path}"
--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
"${hw_proto}"
DEPENDS "${hw_proto}")
# Include generated *.pb.h files
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("${CMAKE_SOURCE_DIR}")
# hw_grpc_proto
add_library(hw_grpc_proto
${hw_grpc_srcs}
${hw_grpc_hdrs}
${hw_proto_srcs}
${hw_proto_hdrs})
target_link_libraries(hw_grpc_proto
${_REFLECTION}
${_GRPC_GRPCPP}
${_PROTOBUF_LIBPROTOBUF})
# util
add_library(util
"util.cc")
target_link_libraries(util
hw_grpc_proto
opentelemetry-cpp::metrics
${_GRPC_GRPCPP}
${_REFLECTION}
${_PROTOBUF_LIBPROTOBUF})
# Targets greeter_callback_(client|server) greeter_callback_(client|server)_solution
foreach(_target
greeter_callback_client greeter_callback_server greeter_callback_client_solution greeter_callback_server_solution)
add_executable(${_target} "${_target}.cc")
target_link_libraries(${_target}
absl::flags
absl::flags_parse
opentelemetry-cpp::metrics
opentelemetry-cpp::prometheus_exporter
gRPC::grpcpp_otel_plugin
util)
endforeach()

@ -0,0 +1,138 @@
/*
*
* 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.
*
*/
// Explicitly define HAVE_ABSEIL to avoid conflict with OTel's Abseil
// version. Refer
// https://github.com/open-telemetry/opentelemetry-cpp/issues/1042.
#ifndef HAVE_ABSEIL
#define HAVE_ABSEIL
#endif
#include <condition_variable>
#include <mutex>
#include <string>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "opentelemetry/exporters/prometheus/exporter_factory.h"
#include "opentelemetry/exporters/prometheus/exporter_options.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include <grpcpp/ext/otel_plugin.h>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/codelab/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
ABSL_FLAG(std::string, target, "localhost:50051", "Server address");
ABSL_FLAG(std::string, prometheus_endpoint, "localhost:9465",
"Prometheus exporter endpoint");
namespace {
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// The actual RPC.
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->SayHello(&context, &request, &reply,
[&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
while (!done) {
cv.wait(lock);
}
// Act upon its status.
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
void RunClient(const std::string& target_str) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint specified by
// the argument "--target=" which is the only expected argument.
grpc::ChannelArguments args;
// Continuously send RPCs every second.
while (true) {
GreeterClient greeter(grpc::CreateCustomChannel(
target_str, grpc::InsecureChannelCredentials(), args));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
} // namespace
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
// CODELAB HINT : Add code to register gRPC OpenTelemetry plugin here.
// Continuously send RPCs.
RunClient(absl::GetFlag(FLAGS_target));
return 0;
}

@ -0,0 +1,158 @@
/*
*
* 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.
*
*/
// Explicitly define HAVE_ABSEIL to avoid conflict with OTel's Abseil
// version. Refer
// https://github.com/open-telemetry/opentelemetry-cpp/issues/1042.
#ifndef HAVE_ABSEIL
#define HAVE_ABSEIL
#endif
#include <condition_variable>
#include <mutex>
#include <string>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "opentelemetry/exporters/prometheus/exporter_factory.h"
#include "opentelemetry/exporters/prometheus/exporter_options.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include <grpcpp/ext/otel_plugin.h>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/codelab/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
ABSL_FLAG(std::string, target, "localhost:50051", "Server address");
ABSL_FLAG(std::string, prometheus_endpoint, "localhost:9465",
"Prometheus exporter endpoint");
namespace {
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SayHello(const std::string& user) {
// Data we are sending to the server.
HelloRequest request;
request.set_name(user);
// Container for the data we expect from the server.
HelloReply reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// The actual RPC.
std::mutex mu;
std::condition_variable cv;
bool done = false;
Status status;
stub_->async()->SayHello(&context, &request, &reply,
[&mu, &cv, &done, &status](Status s) {
status = std::move(s);
std::lock_guard<std::mutex> lock(mu);
done = true;
cv.notify_one();
});
std::unique_lock<std::mutex> lock(mu);
while (!done) {
cv.wait(lock);
}
// Act upon its status.
if (status.ok()) {
return reply.message();
} else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
void RunClient(const std::string& target_str) {
// Instantiate the client. It requires a channel, out of which the actual RPCs
// are created. This channel models a connection to an endpoint specified by
// the argument "--target=" which is the only expected argument.
grpc::ChannelArguments args;
// Continuously send RPCs every second.
while (true) {
GreeterClient greeter(grpc::CreateCustomChannel(
target_str, grpc::InsecureChannelCredentials(), args));
std::string user("world");
std::string reply = greeter.SayHello(user);
std::cout << "Greeter received: " << reply << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
} // namespace
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
// CODELAB HINT : Add code to register OpenTelemetry plugin here.
// Register a global gRPC OpenTelemetry plugin configured with a prometheus
// exporter.
opentelemetry::exporter::metrics::PrometheusExporterOptions opts;
opts.url = absl::GetFlag(FLAGS_prometheus_endpoint);
auto prometheus_exporter =
opentelemetry::exporter::metrics::PrometheusExporterFactory::Create(opts);
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
// The default histogram boundaries are not granular enough for RPCs. Override
// the "grpc.client.attempt.duration" view as recommended by
// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md.
AddLatencyView(meter_provider.get(), "grpc.client.attempt.duration", "s");
meter_provider->AddMetricReader(std::move(prometheus_exporter));
auto status = grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(std::move(meter_provider))
.BuildAndRegisterGlobal();
if (!status.ok()) {
std::cerr << "Failed to register gRPC OpenTelemetry Plugin: "
<< status.ToString() << std::endl;
return static_cast<int>(status.code());
}
// Continuously send RPCs.
RunClient(absl::GetFlag(FLAGS_target));
return 0;
}

@ -0,0 +1,112 @@
/*
*
* 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.
*
*/
// Explicitly define HAVE_ABSEIL to avoid conflict with OTel's Abseil
// version. Refer
// https://github.com/open-telemetry/opentelemetry-cpp/issues/1042.
#ifndef HAVE_ABSEIL
#define HAVE_ABSEIL
#endif
#include <iostream>
#include <memory>
#include <string>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/str_format.h"
#include "opentelemetry/exporters/prometheus/exporter_factory.h"
#include "opentelemetry/exporters/prometheus/exporter_options.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include <grpcpp/ext/otel_plugin.h>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/codelab/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
ABSL_FLAG(uint16_t, port, 50051, "Server port for the service");
ABSL_FLAG(std::string, prometheus_endpoint, "localhost:9464",
"Prometheus exporter endpoint");
namespace {
using grpc::CallbackServerContext;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerUnaryReactor;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::CallbackService {
ServerUnaryReactor* SayHello(CallbackServerContext* context,
const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
// CODELAB HINT: This sleep seems suspicious.
std::this_thread::sleep_for(std::chrono::seconds(5));
ServerUnaryReactor* reactor = context->DefaultReactor();
reactor->Finish(Status::OK);
return reactor;
}
};
void RunServer(uint16_t port) {
std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
GreeterServiceImpl service;
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
} // namespace
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
// CODELAB HINT : Add code to register gRPC OpenTelemetry plugin here.
RunServer(absl::GetFlag(FLAGS_port));
return 0;
}

@ -0,0 +1,127 @@
/*
*
* 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.
*
*/
// Explicitly define HAVE_ABSEIL to avoid conflict with OTel's Abseil
// version. Refer
// https://github.com/open-telemetry/opentelemetry-cpp/issues/1042.
#ifndef HAVE_ABSEIL
#define HAVE_ABSEIL
#endif
#include <iostream>
#include <memory>
#include <string>
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/str_format.h"
#include "opentelemetry/exporters/prometheus/exporter_factory.h"
#include "opentelemetry/exporters/prometheus/exporter_options.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include <grpcpp/ext/otel_plugin.h>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/codelab/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
ABSL_FLAG(uint16_t, port, 50051, "Server port for the service");
ABSL_FLAG(std::string, prometheus_endpoint, "localhost:9464",
"Prometheus exporter endpoint");
namespace {
using grpc::CallbackServerContext;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerUnaryReactor;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::CallbackService {
ServerUnaryReactor* SayHello(CallbackServerContext* context,
const HelloRequest* request,
HelloReply* reply) override {
std::string prefix("Hello ");
reply->set_message(prefix + request->name());
ServerUnaryReactor* reactor = context->DefaultReactor();
reactor->Finish(Status::OK);
return reactor;
}
};
void RunServer(uint16_t port) {
std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
GreeterServiceImpl service;
grpc::EnableDefaultHealthCheckService(true);
grpc::reflection::InitProtoReflectionServerBuilderPlugin();
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
} // namespace
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
// Register a global gRPC OpenTelemetry plugin configured with a prometheus
// exporter.
opentelemetry::exporter::metrics::PrometheusExporterOptions opts;
opts.url = absl::GetFlag(FLAGS_prometheus_endpoint);
auto prometheus_exporter =
opentelemetry::exporter::metrics::PrometheusExporterFactory::Create(opts);
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
// The default histogram boundaries are not granular enough for RPCs. Override
// the "grpc.server.call.duration" view as recommended by
// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md.
AddLatencyView(meter_provider.get(), "grpc.server.call.duration", "s");
meter_provider->AddMetricReader(std::move(prometheus_exporter));
auto status = grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(std::move(meter_provider))
.BuildAndRegisterGlobal();
if (!status.ok()) {
std::cerr << "Failed to register gRPC OpenTelemetry Plugin: "
<< status.ToString() << std::endl;
return static_cast<int>(status.code());
}
RunServer(absl::GetFlag(FLAGS_port));
return 0;
}

@ -0,0 +1,70 @@
//
//
// Copyright 2024 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.
//
//
// Explicitly define HAVE_ABSEIL to avoid conflict with OTel's Abseil
// version. Refer
// https://github.com/open-telemetry/opentelemetry-cpp/issues/1042.
#ifndef HAVE_ABSEIL
#define HAVE_ABSEIL
#endif
#include "opentelemetry/sdk/metrics/view/instrument_selector_factory.h"
#include "opentelemetry/sdk/metrics/view/meter_selector_factory.h"
#include "opentelemetry/sdk/metrics/view/view_factory.h"
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/cpp/otel/codelab/util.h"
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#include "util.h"
#endif
using grpc::CallbackServerContext;
using grpc::Channel;
using grpc::ClientContext;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerUnaryReactor;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;
void AddLatencyView(opentelemetry::sdk::metrics::MeterProvider* provider,
const std::string& name, const std::string& unit) {
auto histogram_config = std::make_shared<
opentelemetry::sdk::metrics::HistogramAggregationConfig>();
histogram_config->boundaries_ = {
0, 0.00001, 0.00005, 0.0001, 0.0003, 0.0006, 0.0008, 0.001, 0.002,
0.003, 0.004, 0.005, 0.006, 0.008, 0.01, 0.013, 0.016, 0.02,
0.025, 0.03, 0.04, 0.05, 0.065, 0.08, 0.1, 0.13, 0.16,
0.2, 0.25, 0.3, 0.4, 0.5, 0.65, 0.8, 1, 2,
5, 10, 20, 50, 100};
provider->AddView(
opentelemetry::sdk::metrics::InstrumentSelectorFactory::Create(
opentelemetry::sdk::metrics::InstrumentType::kHistogram, name, unit),
opentelemetry::sdk::metrics::MeterSelectorFactory::Create(
"grpc-c++", grpc::Version(), ""),
opentelemetry::sdk::metrics::ViewFactory::Create(
name, "", unit,
opentelemetry::sdk::metrics::AggregationType::kHistogram,
std::move(histogram_config)));
}

@ -0,0 +1,31 @@
//
//
// Copyright 2024 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 GRPCPP_EXAMPLES_CPP_OTEL_CODELAB_UTIL_H
#define GRPCPP_EXAMPLES_CPP_OTEL_CODELAB_UTIL_H
#include <string>
#include "opentelemetry/sdk/metrics/meter_provider.h"
// Helper function that adds view for gRPC latency instrument \a name with unit
// \a unit with bucket boundaries that are more useful for RPCs.
void AddLatencyView(opentelemetry::sdk::metrics::MeterProvider* provider,
const std::string& name, const std::string& unit);
#endif // GRPCPP_EXAMPLES_CPP_OTEL_UTIL_H

@ -72,7 +72,8 @@ target_link_libraries(route_guide_helper
# Targets route_guide_(client|server)
foreach(_target
route_guide_client route_guide_server)
route_guide_client route_guide_server
route_guide_callback_client route_guide_callback_server)
add_executable(${_target}
"${_target}.cc")
target_link_libraries(${_target}

4
gRPC-C++.podspec generated

@ -374,7 +374,6 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/legacy_frame.h',
'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h',
'src/core/ext/transport/chttp2/transport/ping_abuse_policy.h',
'src/core/ext/transport/chttp2/transport/ping_callbacks.h',
'src/core/ext/transport/chttp2/transport/ping_rate_policy.h',
@ -1322,6 +1321,7 @@ Pod::Spec.new do |s|
'src/core/util/json/json_util.h',
'src/core/util/json/json_writer.h',
'src/core/util/latent_see.h',
'src/core/util/ring_buffer.h',
'src/core/util/spinlock.h',
'src/core/util/string.h',
'src/core/util/time_precise.h',
@ -1657,7 +1657,6 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/legacy_frame.h',
'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h',
'src/core/ext/transport/chttp2/transport/ping_abuse_policy.h',
'src/core/ext/transport/chttp2/transport/ping_callbacks.h',
'src/core/ext/transport/chttp2/transport/ping_rate_policy.h',
@ -2605,6 +2604,7 @@ Pod::Spec.new do |s|
'src/core/util/json/json_util.h',
'src/core/util/json/json_writer.h',
'src/core/util/latent_see.h',
'src/core/util/ring_buffer.h',
'src/core/util/spinlock.h',
'src/core/util/string.h',
'src/core/util/time_precise.h',

5
gRPC-Core.podspec generated

@ -364,8 +364,6 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/legacy_frame.h',
'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc',
'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h',
'src/core/ext/transport/chttp2/transport/parsing.cc',
'src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc',
'src/core/ext/transport/chttp2/transport/ping_abuse_policy.h',
@ -2058,6 +2056,7 @@ Pod::Spec.new do |s|
'src/core/util/posix/sync.cc',
'src/core/util/posix/time.cc',
'src/core/util/posix/tmpfile.cc',
'src/core/util/ring_buffer.h',
'src/core/util/spinlock.h',
'src/core/util/string.cc',
'src/core/util/string.h',
@ -2438,7 +2437,6 @@ Pod::Spec.new do |s|
'src/core/ext/transport/chttp2/transport/huffsyms.h',
'src/core/ext/transport/chttp2/transport/internal.h',
'src/core/ext/transport/chttp2/transport/legacy_frame.h',
'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h',
'src/core/ext/transport/chttp2/transport/ping_abuse_policy.h',
'src/core/ext/transport/chttp2/transport/ping_callbacks.h',
'src/core/ext/transport/chttp2/transport/ping_rate_policy.h',
@ -3386,6 +3384,7 @@ Pod::Spec.new do |s|
'src/core/util/json/json_util.h',
'src/core/util/json/json_writer.h',
'src/core/util/latent_see.h',
'src/core/util/ring_buffer.h',
'src/core/util/spinlock.h',
'src/core/util/string.h',
'src/core/util/time_precise.h',

3
grpc.gemspec generated

@ -250,8 +250,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/transport/chttp2/transport/huffsyms.h )
s.files += %w( src/core/ext/transport/chttp2/transport/internal.h )
s.files += %w( src/core/ext/transport/chttp2/transport/legacy_frame.h )
s.files += %w( src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc )
s.files += %w( src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h )
s.files += %w( src/core/ext/transport/chttp2/transport/parsing.cc )
s.files += %w( src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc )
s.files += %w( src/core/ext/transport/chttp2/transport/ping_abuse_policy.h )
@ -1944,6 +1942,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/util/posix/sync.cc )
s.files += %w( src/core/util/posix/time.cc )
s.files += %w( src/core/util/posix/tmpfile.cc )
s.files += %w( src/core/util/ring_buffer.h )
s.files += %w( src/core/util/spinlock.h )
s.files += %w( src/core/util/string.cc )
s.files += %w( src/core/util/string.h )

3
package.xml generated

@ -232,8 +232,6 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/huffsyms.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/internal.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/legacy_frame.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/parsing.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/ping_abuse_policy.h" role="src" />
@ -1926,6 +1924,7 @@
<file baseinstalldir="/" name="src/core/util/posix/sync.cc" role="src" />
<file baseinstalldir="/" name="src/core/util/posix/time.cc" role="src" />
<file baseinstalldir="/" name="src/core/util/posix/tmpfile.cc" role="src" />
<file baseinstalldir="/" name="src/core/util/ring_buffer.h" role="src" />
<file baseinstalldir="/" name="src/core/util/spinlock.h" role="src" />
<file baseinstalldir="/" name="src/core/util/string.cc" role="src" />
<file baseinstalldir="/" name="src/core/util/string.h" role="src" />

@ -148,10 +148,25 @@ grpc_cc_library(
],
deps = [
"per_cpu",
"ring_buffer",
"//:gpr",
],
)
grpc_cc_library(
name = "ring_buffer",
srcs = [],
hdrs = [
"util/ring_buffer.h",
],
external_deps = [
"absl/types:optional",
],
deps = [
"//:gpr_platform",
],
)
grpc_cc_library(
name = "transport_fwd",
hdrs = [
@ -7188,23 +7203,6 @@ grpc_cc_library(
],
)
grpc_cc_library(
name = "max_concurrent_streams_policy",
srcs = [
"ext/transport/chttp2/transport/max_concurrent_streams_policy.cc",
],
hdrs = [
"ext/transport/chttp2/transport/max_concurrent_streams_policy.h",
],
external_deps = [
"absl/log:check",
],
deps = [
"//:gpr",
"//:gpr_platform",
],
)
grpc_cc_library(
name = "huffsyms",
srcs = [

@ -65,7 +65,6 @@
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
#include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
#include "src/core/ext/transport/chttp2/transport/ping_abuse_policy.h"
#include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
#include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
@ -547,7 +546,6 @@ static void read_channel_args(grpc_chttp2_transport* t,
value = channel_args.GetInt(GRPC_ARG_MAX_CONCURRENT_STREAMS).value_or(-1);
if (value >= 0) {
t->settings.mutable_local().SetMaxConcurrentStreams(value);
t->max_concurrent_streams_policy.SetTarget(value);
}
} else if (channel_args.Contains(GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
VLOG(2) << GRPC_ARG_MAX_CONCURRENT_STREAMS

@ -52,7 +52,6 @@
#include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
#include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
#include "src/core/ext/transport/chttp2/transport/ping_abuse_policy.h"
#include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
#include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
@ -383,8 +382,6 @@ struct grpc_chttp2_transport final : public grpc_core::FilterStackTransport,
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid;
grpc_closure retry_initiate_ping_locked;
grpc_core::Chttp2MaxConcurrentStreamsPolicy max_concurrent_streams_policy;
/// ping acks
size_t ping_ack_count = 0;
size_t ping_ack_capacity = 0;

@ -1,45 +0,0 @@
// 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 "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
#include <utility>
#include "absl/log/check.h"
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
namespace grpc_core {
void Chttp2MaxConcurrentStreamsPolicy::AddDemerit() {
++new_demerits_;
++unacked_demerits_;
}
void Chttp2MaxConcurrentStreamsPolicy::FlushedSettings() {
sent_demerits_ += std::exchange(new_demerits_, 0);
}
void Chttp2MaxConcurrentStreamsPolicy::AckLastSend() {
CHECK(unacked_demerits_ >= sent_demerits_);
unacked_demerits_ -= std::exchange(sent_demerits_, 0);
}
uint32_t Chttp2MaxConcurrentStreamsPolicy::AdvertiseValue() const {
if (target_ < unacked_demerits_) return 0;
return target_ - unacked_demerits_;
}
} // namespace grpc_core

@ -1,67 +0,0 @@
// 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_EXT_TRANSPORT_CHTTP2_TRANSPORT_MAX_CONCURRENT_STREAMS_POLICY_H
#define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_MAX_CONCURRENT_STREAMS_POLICY_H
#include <cstdint>
#include <limits>
#include <grpc/support/port_platform.h>
namespace grpc_core {
class Chttp2MaxConcurrentStreamsPolicy {
public:
// Set the target number of concurrent streams.
// If everything is idle we should advertise this number.
void SetTarget(uint32_t target) { target_ = target; }
// Add one demerit to the current target.
// We need to do one full settings round trip after this to clear this
// demerit.
// It will reduce our advertised max concurrent streams by one.
void AddDemerit();
// Notify the policy that we've sent a settings frame.
// Newly added demerits since the last settings frame was sent will be cleared
// once that settings frame is acknowledged.
void FlushedSettings();
// Notify the policy that we've received an acknowledgement for the last
// settings frame we sent.
void AckLastSend();
// Returns what we should advertise as max concurrent streams.
uint32_t AdvertiseValue() const;
private:
uint32_t target_ = std::numeric_limits<int32_t>::max();
// Demerit flow:
// When we add a demerit, we add to both new & unacked.
// When we flush settings, we move new to sent.
// When we ack settings, we remove what we sent from unacked.
// eg:
// we add 10 demerits - now new=10, sent=0, unacked=10
// we send settings - now new=0, sent=10, unacked=10
// we add 5 demerits - now new=5, sent=10, unacked=15
// we get the settings ack - now new=5, sent=0, unacked=5
uint32_t new_demerits_ = 0;
uint32_t sent_demerits_ = 0;
uint32_t unacked_demerits_ = 0;
};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_MAX_CONCURRENT_STREAMS_POLICY_H

@ -55,7 +55,6 @@
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
#include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
#include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
#include "src/core/lib/backoff/random_early_detection.h"
#include "src/core/lib/debug/trace.h"
@ -650,7 +649,7 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
} else if (GPR_UNLIKELY(
t->max_concurrent_streams_overload_protection &&
t->streams_allocated.load(std::memory_order_relaxed) >
t->max_concurrent_streams_policy.AdvertiseValue())) {
t->settings.local().max_concurrent_streams())) {
// We have more streams allocated than we'd like, so apply some pushback
// by refusing this stream.
++t->num_pending_induced_frames;
@ -659,11 +658,10 @@ static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t,
GRPC_HTTP2_REFUSED_STREAM, nullptr));
grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
return init_header_skip_frame_parser(t, priority_type, is_eoh);
} else if (GPR_UNLIKELY(
t->stream_map.size() >=
t->max_concurrent_streams_policy.AdvertiseValue() &&
} else if (GPR_UNLIKELY(t->stream_map.size() >=
t->settings.local().max_concurrent_streams() &&
grpc_core::RandomEarlyDetection(
t->max_concurrent_streams_policy.AdvertiseValue(),
t->settings.local().max_concurrent_streams(),
t->settings.acked().max_concurrent_streams())
.Reject(t->stream_map.size(), t->bitgen))) {
// We are under the limit of max concurrent streams for the current
@ -827,9 +825,6 @@ static grpc_error_handle init_rst_stream_parser(grpc_chttp2_transport* t) {
s->call_tracer_wrapper.RecordIncomingBytes({9, 0, 0});
t->parser = grpc_chttp2_transport::Parser{
"rst_stream", grpc_chttp2_rst_stream_parser_parse, &t->simple.rst_stream};
if (!t->is_client && grpc_core::IsRstpitEnabled()) {
t->max_concurrent_streams_policy.AddDemerit();
}
return absl::OkStatus();
}
@ -854,7 +849,6 @@ static grpc_error_handle init_settings_frame_parser(grpc_chttp2_transport* t) {
return err;
}
if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_ACK) {
t->max_concurrent_streams_policy.AckLastSend();
if (!t->settings.AckLastSend()) {
return GRPC_ERROR_CREATE("Received unexpected settings ack");
}

@ -49,7 +49,6 @@
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
#include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
#include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
#include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
#include "src/core/ext/transport/chttp2/transport/write_size_policy.h"
@ -260,8 +259,6 @@ class WriteContext {
}
void FlushSettings() {
t_->settings.mutable_local().SetMaxConcurrentStreams(
t_->max_concurrent_streams_policy.AdvertiseValue());
auto update = t_->settings.MaybeSendUpdate();
if (update.has_value()) {
grpc_core::Http2Frame frame(std::move(*update));
@ -280,7 +277,6 @@ class WriteContext {
});
}
t_->flow_control.FlushedSettings();
t_->max_concurrent_streams_policy.FlushedSettings();
grpc_core::global_stats().IncrementHttp2SettingsWrites();
}
}

@ -69,10 +69,6 @@ const char* const additional_constraints_pick_first_new = "{}";
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
const char* const additional_constraints_rstpit = "{}";
const char* const description_schedule_cancellation_over_write =
"Allow cancellation op to be scheduled over a write";
const char* const additional_constraints_schedule_cancellation_over_write =
@ -142,8 +138,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport, nullptr, 0, false,
false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
description_schedule_cancellation_over_write,
additional_constraints_schedule_cancellation_over_write, nullptr, 0, false,
@ -219,10 +213,6 @@ const char* const additional_constraints_pick_first_new = "{}";
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
const char* const additional_constraints_rstpit = "{}";
const char* const description_schedule_cancellation_over_write =
"Allow cancellation op to be scheduled over a write";
const char* const additional_constraints_schedule_cancellation_over_write =
@ -292,8 +282,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport, nullptr, 0, false,
false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
description_schedule_cancellation_over_write,
additional_constraints_schedule_cancellation_over_write, nullptr, 0, false,
@ -369,10 +357,6 @@ const char* const additional_constraints_pick_first_new = "{}";
const char* const description_promise_based_inproc_transport =
"Use promises for the in-process transport.";
const char* const additional_constraints_promise_based_inproc_transport = "{}";
const char* const description_rstpit =
"On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short "
"duration";
const char* const additional_constraints_rstpit = "{}";
const char* const description_schedule_cancellation_over_write =
"Allow cancellation op to be scheduled over a write";
const char* const additional_constraints_schedule_cancellation_over_write =
@ -442,8 +426,6 @@ const ExperimentMetadata g_experiment_metadata[] = {
description_promise_based_inproc_transport,
additional_constraints_promise_based_inproc_transport, nullptr, 0, false,
false},
{"rstpit", description_rstpit, additional_constraints_rstpit, nullptr, 0,
false, true},
{"schedule_cancellation_over_write",
description_schedule_cancellation_over_write,
additional_constraints_schedule_cancellation_over_write, nullptr, 0, false,

@ -75,7 +75,6 @@ inline bool IsPeerStateBasedFramingEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
inline bool IsServerPrivacyEnabled() { return false; }
inline bool IsTcpFrameSizeTuningEnabled() { return false; }
@ -109,7 +108,6 @@ inline bool IsPeerStateBasedFramingEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
inline bool IsServerPrivacyEnabled() { return false; }
inline bool IsTcpFrameSizeTuningEnabled() { return false; }
@ -142,7 +140,6 @@ inline bool IsPeerStateBasedFramingEnabled() { return false; }
#define GRPC_EXPERIMENT_IS_INCLUDED_PICK_FIRST_NEW
inline bool IsPickFirstNewEnabled() { return true; }
inline bool IsPromiseBasedInprocTransportEnabled() { return false; }
inline bool IsRstpitEnabled() { return false; }
inline bool IsScheduleCancellationOverWriteEnabled() { return false; }
inline bool IsServerPrivacyEnabled() { return false; }
inline bool IsTcpFrameSizeTuningEnabled() { return false; }
@ -171,7 +168,6 @@ enum ExperimentIds {
kExperimentIdPeerStateBasedFraming,
kExperimentIdPickFirstNew,
kExperimentIdPromiseBasedInprocTransport,
kExperimentIdRstpit,
kExperimentIdScheduleCancellationOverWrite,
kExperimentIdServerPrivacy,
kExperimentIdTcpFrameSizeTuning,
@ -238,10 +234,6 @@ inline bool IsPickFirstNewEnabled() {
inline bool IsPromiseBasedInprocTransportEnabled() {
return IsExperimentEnabled<kExperimentIdPromiseBasedInprocTransport>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_RSTPIT
inline bool IsRstpitEnabled() {
return IsExperimentEnabled<kExperimentIdRstpit>();
}
#define GRPC_EXPERIMENT_IS_INCLUDED_SCHEDULE_CANCELLATION_OVER_WRITE
inline bool IsScheduleCancellationOverWriteEnabled() {
return IsExperimentEnabled<kExperimentIdScheduleCancellationOverWrite>();

@ -130,12 +130,6 @@
owner: ctiller@google.com
test_tags: []
allow_in_fuzzing_config: false # experiment currently crashes if enabled
- name: rstpit
description:
On RST_STREAM on a server, reduce MAX_CONCURRENT_STREAMS for a short duration
expiry: 2024/08/03
owner: ctiller@google.com
test_tags: [flow_control_test]
- name: schedule_cancellation_over_write
description: Allow cancellation op to be scheduled over a write
expiry: 2024/08/01

@ -334,6 +334,15 @@ class Table {
absl::index_sequence<table_detail::IndexOf<Vs, Ts...>()...>());
}
// Iterate through each set field in the table if it exists in Vs, in the
// order of Vs. For each existing field, call the filter function. If the
// function returns true, keep the field. Otherwise, remove the field.
template <typename F, typename... Vs>
void FilterIn(F f) {
FilterInImpl(std::move(f),
absl::index_sequence<table_detail::IndexOf<Vs, Ts...>()...>());
}
// Count the number of set fields in the table
size_t count() const { return present_bits_.count(); }
@ -415,6 +424,18 @@ class Table {
}
}
// Call (*f)(value) if that value is in the table.
// If the value is present in the table and (*f)(value) returns false, remove
// the value from the table.
template <size_t I, typename F>
void FilterIf(F* f) {
if (auto* p = get<I>()) {
if (!(*f)(*p)) {
clear<I>();
}
}
}
// For each field (element I=0, 1, ...) if that field is present, call its
// destructor.
template <size_t... I>
@ -444,6 +465,13 @@ class Table {
table_detail::do_these_things<int>({(CallIf<I>(&f), 1)...});
}
// For each field (element I=0, 1, ...) if that field is present, call f. If
// f returns false, remove the field from the table.
template <typename F, size_t... I>
void FilterInImpl(F f, absl::index_sequence<I...>) {
table_detail::do_these_things<int>({(FilterIf<I>(&f), 1)...});
}
template <size_t... I>
void ClearAllImpl(absl::index_sequence<I...>) {
table_detail::do_these_things<int>({(clear<I>(), 1)...});

@ -276,7 +276,7 @@ void Party::RunPartyAndUnref(uint64_t prev_state) {
auto wakeup_mask = std::exchange(wakeup_mask_, 0);
while (wakeup_mask != 0) {
const uint64_t t = LowestOneBit(wakeup_mask);
const int i = CountTrailingZeros(t);
const int i = absl::countr_zero(t);
wakeup_mask ^= t;
// If the participant is null, skip.
// This allows participants to complete whilst wakers still exist
@ -364,7 +364,7 @@ void Party::AddParticipants(Participant** participants, size_t count) {
}
wakeup_mask |= new_mask;
allocated |= new_mask;
slots[i] = CountTrailingZeros(new_mask);
slots[i] = absl::countr_zero(new_mask);
}
// Try to allocate this slot and take a ref (atomically).
// Ref needs to be taken because once we store the participant it could be
@ -406,7 +406,7 @@ void Party::AddParticipant(Participant* participant) {
<< "No available slots for new participant; allocated=" << allocated
<< " state=" << state << " wakeup_mask=" << wakeup_mask;
allocated |= wakeup_mask;
slot = CountTrailingZeros(wakeup_mask);
slot = absl::countr_zero(wakeup_mask);
// Try to allocate this slot and take a ref (atomically).
// Ref needs to be taken because once we store the participant it could be
// spuriously woken up and unref the party.

@ -1052,6 +1052,26 @@ struct LogWrapper {
}
};
// Callable for the table FilterIn -- for each value, call the
// appropriate filter method to determine of the value should be kept or
// removed.
template <typename Filterer>
struct FilterWrapper {
Filterer filter_fn;
template <typename Which,
absl::enable_if_t<IsEncodableTrait<Which>::value, bool> = true>
bool operator()(const Value<Which>& /*which*/) {
return filter_fn(Which());
}
template <typename Which,
absl::enable_if_t<!IsEncodableTrait<Which>::value, bool> = true>
bool operator()(const Value<Which>& /*which*/) {
return true;
}
};
// Encoder to compute TransportSize
class TransportSizeEncoder {
public:
@ -1094,6 +1114,16 @@ class UnknownMap {
BackingType::const_iterator begin() const { return unknown_.cbegin(); }
BackingType::const_iterator end() const { return unknown_.cend(); }
template <typename Filterer>
void Filter(Filterer* filter_fn) {
unknown_.erase(
std::remove_if(unknown_.begin(), unknown_.end(),
[&](auto& pair) {
return !(*filter_fn)(pair.first.as_string_view());
}),
unknown_.end());
}
bool empty() const { return unknown_.empty(); }
size_t size() const { return unknown_.size(); }
void Clear() { unknown_.clear(); }
@ -1314,6 +1344,17 @@ class MetadataMap {
}
}
// Filter the metadata map.
// Iterates over all encodable and unknown headers and calls the filter_fn
// for each of them. If the function returns true, the header is kept.
template <typename Filterer>
void Filter(Filterer filter_fn) {
table_.template FilterIn<metadata_detail::FilterWrapper<Filterer>,
Value<Traits>...>(
metadata_detail::FilterWrapper<Filterer>{filter_fn});
unknown_.Filter<Filterer>(&filter_fn);
}
std::string DebugString() const {
metadata_detail::DebugStringBuilder builder;
Log([&builder](absl::string_view key, absl::string_view value) {

@ -15,12 +15,19 @@
#include "src/core/util/latent_see.h"
#ifdef GRPC_ENABLE_LATENT_SEE
#include <atomic>
#include <chrono>
#include <cstdint>
#include <string>
#include <vector>
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/util/ring_buffer.h"
namespace grpc_core {
namespace latent_see {
@ -34,7 +41,10 @@ std::string Log::GenerateJson() {
std::vector<RecordedEvent> events;
for (auto& fragment : fragments_) {
MutexLock lock(&fragment.mu);
events.insert(events.end(), fragment.events.begin(), fragment.events.end());
for (auto it = fragment.events.begin(); it != fragment.events.end(); ++it) {
events.push_back(*it);
}
fragment.events.Clear();
}
absl::optional<std::chrono::steady_clock::time_point> start_time;
for (auto& event : events) {
@ -103,7 +113,7 @@ void Log::FlushBin(Bin* bin) {
{
MutexLock lock(&fragment.mu);
for (auto event : bin->events) {
fragment.events.push_back(RecordedEvent{thread_id, batch_id, event});
fragment.events.Append(RecordedEvent{thread_id, batch_id, event});
}
}
bin->events.clear();

@ -18,8 +18,12 @@
#include <grpc/support/port_platform.h>
#ifdef GRPC_ENABLE_LATENT_SEE
#include <atomic>
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <utility>
#include <vector>
@ -27,6 +31,7 @@
#include "src/core/lib/gprpp/per_cpu.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/util/ring_buffer.h"
namespace grpc_core {
namespace latent_see {
@ -59,6 +64,7 @@ struct Bin {
class Log {
public:
static constexpr int kMaxEventsPerCpu = 50000;
static Bin* MaybeStartBin(void* owner) {
if (bin_ != nullptr) return bin_;
Bin* bin = free_bins_.load(std::memory_order_acquire);
@ -120,7 +126,7 @@ class Log {
static std::atomic<Bin*> free_bins_;
struct Fragment {
Mutex mu;
std::vector<RecordedEvent> events ABSL_GUARDED_BY(mu);
RingBuffer<RecordedEvent, Log::kMaxEventsPerCpu> events ABSL_GUARDED_BY(mu);
};
PerCpu<Fragment> fragments_{PerCpuOptions()};
};

@ -0,0 +1,123 @@
// Copyright 2024 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_UTIL_RING_BUFFER_H
#define GRPC_SRC_CORE_UTIL_RING_BUFFER_H
#include <grpc/support/port_platform.h>
#include <array>
#include <cstddef>
#include <iterator>
#include "absl/types/optional.h"
namespace grpc_core {
template <typename T, int kCapacity>
class RingBuffer {
public:
class RingBufferIterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = const T;
using pointer = void;
using reference = void;
using difference_type = std::ptrdiff_t;
RingBufferIterator& operator++() {
if (--size_ <= 0) {
head_ = 0;
size_ = 0;
buffer_ = nullptr;
} else {
head_ = (head_ + 1) % kCapacity;
}
return *this;
}
RingBufferIterator operator++(int) {
RingBufferIterator tmp(*this);
operator++();
return tmp;
}
bool operator==(const RingBufferIterator& rhs) const {
return (buffer_ == rhs.buffer_ && head_ == rhs.head_ &&
size_ == rhs.size_);
}
bool operator!=(const RingBufferIterator& rhs) const {
return !operator==(rhs);
}
T operator*() { return buffer_->data_[head_]; }
RingBufferIterator() : buffer_(nullptr), head_(0), size_(0){};
RingBufferIterator(const RingBufferIterator& other) = default;
explicit RingBufferIterator(const RingBuffer<T, kCapacity>* buffer)
: buffer_(buffer), head_(buffer->head_), size_(buffer->size_) {
if (!size_) {
buffer_ = nullptr;
}
}
private:
friend class RingBuffer<T, kCapacity>;
const RingBuffer<T, kCapacity>* buffer_;
int head_ = 0;
int size_ = 0;
};
RingBuffer() = default;
void Append(T data) {
if (size_ < kCapacity) {
data_[size_] = std::move(data);
size_++;
} else {
data_[head_] = std::move(data);
head_ = (head_ + 1) % kCapacity;
}
}
// Returns the data of the first element in the buffer and removes it from
// the buffer. If the buffer is empty, returns absl::nullopt.
absl::optional<T> PopIfNotEmpty() {
if (!size_) return absl::nullopt;
T data = std::move(data_[head_]);
--size_;
head_ = (head_ + 1) % kCapacity;
return data;
}
void Clear() {
head_ = 0;
size_ = 0;
}
RingBufferIterator begin() const { return RingBufferIterator(this); }
RingBufferIterator end() const { return RingBufferIterator(); }
private:
friend class RingBufferIterator;
std::array<T, kCapacity> data_;
int head_ = 0;
int size_ = 0;
};
} // namespace grpc_core
#endif // GRPC_SRC_CORE_UTIL_RING_BUFFER_H

@ -57,30 +57,6 @@ bool GetBit(T i, size_t n) {
return (i & (T(1) << n)) != 0;
}
#if GRPC_HAS_BUILTIN(__builtin_ctz)
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros(
uint32_t i) {
DCHECK_NE(i, 0u); // __builtin_ctz returns undefined behavior for 0
return __builtin_ctz(i);
}
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros(
uint64_t i) {
DCHECK_NE(i, 0u); // __builtin_ctz returns undefined behavior for 0
return __builtin_ctzll(i);
}
#else
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros(
uint32_t i) {
DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0
return absl::popcount((i & -i) - 1);
}
GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION inline uint32_t CountTrailingZeros(
uint64_t i) {
DCHECK_NE(i, 0); // __builtin_ctz returns undefined behavior for 0
return absl::popcount((i & -i) - 1);
}
#endif
// This function uses operator< to implement a qsort-style comparison, whereby:
// if a is smaller than b, a number smaller than 0 is returned.
// if a is bigger than b, a number greater than 0 is returned.

@ -75,7 +75,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/transport/chttp2/transport/hpack_parser_table.cc',
'src/core/ext/transport/chttp2/transport/http2_settings.cc',
'src/core/ext/transport/chttp2/transport/huffsyms.cc',
'src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc',
'src/core/ext/transport/chttp2/transport/parsing.cc',
'src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc',
'src/core/ext/transport/chttp2/transport/ping_callbacks.cc',

@ -346,16 +346,6 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "max_concurrent_streams_policy_test",
srcs = ["max_concurrent_streams_policy_test.cc"],
external_deps = ["gtest"],
language = "C++",
deps = [
"//src/core:max_concurrent_streams_policy",
],
)
grpc_cc_test(
name = "streams_not_seen_test",
srcs = ["streams_not_seen_test.cc"],

@ -1,48 +0,0 @@
// 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 "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
#include <memory>
#include "gtest/gtest.h"
namespace grpc_core {
namespace {
TEST(MaxConcurrentStreamsPolicyTest, NoOpWorks) {
Chttp2MaxConcurrentStreamsPolicy policy;
policy.SetTarget(100);
EXPECT_EQ(policy.AdvertiseValue(), 100);
}
TEST(MaxConcurrentStreamsPolicyTest, BasicFlow) {
Chttp2MaxConcurrentStreamsPolicy policy;
policy.SetTarget(100);
EXPECT_EQ(policy.AdvertiseValue(), 100);
policy.AddDemerit();
EXPECT_EQ(policy.AdvertiseValue(), 99);
policy.FlushedSettings();
EXPECT_EQ(policy.AdvertiseValue(), 99);
policy.AckLastSend();
EXPECT_EQ(policy.AdvertiseValue(), 100);
}
} // namespace
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -260,6 +260,83 @@ TEST(DebugStringBuilderTest, TestAllRedacted) {
}
}
std::vector<std::string> GetEncodableHeaders() {
return {
// clang-format off
std::string(ContentTypeMetadata::key()),
std::string(EndpointLoadMetricsBinMetadata::key()),
std::string(GrpcAcceptEncodingMetadata::key()),
std::string(GrpcEncodingMetadata::key()),
std::string(GrpcInternalEncodingRequest::key()),
std::string(GrpcLbClientStatsMetadata::key()),
std::string(GrpcMessageMetadata::key()),
std::string(GrpcPreviousRpcAttemptsMetadata::key()),
std::string(GrpcRetryPushbackMsMetadata::key()),
std::string(GrpcServerStatsBinMetadata::key()),
std::string(GrpcStatusMetadata::key()),
std::string(GrpcTagsBinMetadata::key()),
std::string(GrpcTimeoutMetadata::key()),
std::string(GrpcTraceBinMetadata::key()),
std::string(HostMetadata::key()),
std::string(HttpAuthorityMetadata::key()),
std::string(HttpMethodMetadata::key()),
std::string(HttpPathMetadata::key()),
std::string(HttpSchemeMetadata::key()),
std::string(HttpStatusMetadata::key()),
std::string(LbCostBinMetadata::key()),
std::string(LbTokenMetadata::key()),
std::string(TeMetadata::key()),
// clang-format on
};
}
template <typename NonEncodableHeader, typename Value>
void AddNonEncodableHeader(grpc_metadata_batch& md, Value value) {
md.Set(NonEncodableHeader(), value);
}
template <bool filter_unknown>
class HeaderFilter {
public:
template <typename Key>
bool operator()(Key) {
return filter_unknown;
}
bool operator()(absl::string_view /*key*/) { return !filter_unknown; }
};
TEST(MetadataMapTest, FilterTest) {
grpc_metadata_batch map;
std::vector<std::string> allow_list_keys = GetEncodableHeaders();
std::vector<std::string> unknown_keys = {"unknown_key_1", "unknown_key_2"};
allow_list_keys.insert(allow_list_keys.end(), unknown_keys.begin(),
unknown_keys.end());
// Add some encodable and unknown headers
for (const std::string& curr_key : allow_list_keys) {
map.Append(curr_key, Slice::FromStaticString("value1"),
[](absl::string_view /*error*/, const Slice& /*value*/) {});
}
// Add 5 non-encodable headers
constexpr int kNumNonEncodableHeaders = 5;
AddNonEncodableHeader<GrpcCallWasCancelled, bool>(map, true);
AddNonEncodableHeader<GrpcRegisteredMethod, void*>(map, nullptr);
AddNonEncodableHeader<GrpcStatusContext, std::string>(map, "value1");
AddNonEncodableHeader<GrpcStatusFromWire>(map, "value1");
AddNonEncodableHeader<GrpcStreamNetworkState,
GrpcStreamNetworkState::ValueType>(
map, GrpcStreamNetworkState::kNotSentOnWire);
EXPECT_EQ(map.count(), allow_list_keys.size() + kNumNonEncodableHeaders);
// Remove all unknown headers
map.Filter(HeaderFilter<true>());
EXPECT_EQ(map.count(), allow_list_keys.size() + kNumNonEncodableHeaders -
unknown_keys.size());
// Remove all encodable headers
map.Filter(HeaderFilter<false>());
EXPECT_EQ(map.count(), kNumNonEncodableHeaders);
}
} // namespace testing
} // namespace grpc_core

@ -124,3 +124,16 @@ grpc_cc_test(
"//src/core:useful",
],
)
grpc_cc_test(
name = "ring_buffer_test",
srcs = ["ring_buffer_test.cc"],
external_deps = ["gtest"],
language = "C++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//:gpr_platform",
"//src/core:ring_buffer",
],
)

@ -0,0 +1,89 @@
//
//
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#include "src/core/util/ring_buffer.h"
#include "gtest/gtest.h"
#include <grpc/support/port_platform.h>
namespace grpc_core {
constexpr int kBufferCapacity = 1000;
TEST(RingBufferTest, BufferAppendPopTest) {
RingBuffer<int, kBufferCapacity> buffer;
EXPECT_FALSE(buffer.PopIfNotEmpty().has_value());
for (int i = 0; i < (3 * kBufferCapacity) / 2; ++i) {
buffer.Append(i);
}
// Pop half of the elements. Elements in [kBufferCapacity / 2,
// kBufferCapacity) are popped.
int j = kBufferCapacity / 2;
for (int i = 0; i < kBufferCapacity / 2; ++i) {
EXPECT_EQ(buffer.PopIfNotEmpty(), j++);
}
EXPECT_EQ(j, kBufferCapacity);
// Iterate over the remaining elements.
for (auto it = buffer.begin(); it != buffer.end(); ++it) {
EXPECT_EQ(*it, j++);
}
// Elements in [kBufferCapacity, (3 * kBufferCapacity) / 2) should be present.
EXPECT_EQ(j, (3 * kBufferCapacity) / 2);
// Append some more elements. The buffer should now have elements in
// [kBufferCapacity, 2 * kBufferCapacity).
for (int i = 0; i < kBufferCapacity / 2; ++i) {
buffer.Append(j++);
}
// Pop all the elements.
j = kBufferCapacity;
while (true) {
auto ret = buffer.PopIfNotEmpty();
if (!ret.has_value()) break;
EXPECT_EQ(*ret, j++);
}
EXPECT_EQ(j, 2 * kBufferCapacity);
}
TEST(RingBufferTest, BufferAppendIterateTest) {
RingBuffer<int, kBufferCapacity> buffer;
for (int i = 0; i < 5 * kBufferCapacity; ++i) {
buffer.Append(i);
int j = std::max(0, i + 1 - kBufferCapacity);
// If i >= kBufferCapacity, check that the buffer contains only the last
// kBufferCapacity elements [i + 1 - kBufferCapacity, i]. Otherwise check
// that the buffer contains all elements from 0 to i.
for (auto it = buffer.begin(); it != buffer.end(); ++it) {
EXPECT_EQ(*it, j++);
}
// Check that j was incremented at each step which implies that all the
// required elements were present in the buffer.
EXPECT_EQ(j, i + 1);
}
buffer.Clear();
EXPECT_EQ(buffer.begin(), buffer.end());
}
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -81,55 +81,6 @@ TEST(UsefulTest, RoundUpToPowerOf2) {
EXPECT_EQ(RoundUpToPowerOf2(8), 8);
}
TEST(UsefulTest, CountTrailingZeros32) {
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(1)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(2)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(3)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(4)), 2);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(5)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(6)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(7)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(8)), 3);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(9)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(10)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(11)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(12)), 2);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(13)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(14)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(15)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(16)), 4);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(256)), 8);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(65535)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(65536)), 16);
EXPECT_EQ(CountTrailingZeros(static_cast<uint32_t>(0x80000000)), 31);
}
TEST(UsefulTest, CountTrailingZeros64) {
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(1)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(2)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(3)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(4)), 2);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(5)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(6)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(7)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(8)), 3);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(9)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(10)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(11)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(12)), 2);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(13)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(14)), 1);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(15)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(16)), 4);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(256)), 8);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(65535)), 0);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(65536)), 16);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(0x80000000)), 31);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(0x100000000)), 32);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(0x1000000000000)), 48);
EXPECT_EQ(CountTrailingZeros(static_cast<uint64_t>(0x8000000000000000)), 63);
}
TEST(UsefulTest, LowestOneBit8) {
EXPECT_EQ(LowestOneBit(static_cast<uint8_t>(0)), 0);
EXPECT_EQ(LowestOneBit(static_cast<uint8_t>(1)), 1);

@ -1254,8 +1254,6 @@ src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/huffsyms.h \
src/core/ext/transport/chttp2/transport/internal.h \
src/core/ext/transport/chttp2/transport/legacy_frame.h \
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc \
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc \
src/core/ext/transport/chttp2/transport/ping_abuse_policy.h \
@ -2948,6 +2946,7 @@ src/core/util/posix/string.cc \
src/core/util/posix/sync.cc \
src/core/util/posix/time.cc \
src/core/util/posix/tmpfile.cc \
src/core/util/ring_buffer.h \
src/core/util/spinlock.h \
src/core/util/string.cc \
src/core/util/string.h \

@ -1022,8 +1022,6 @@ src/core/ext/transport/chttp2/transport/huffsyms.cc \
src/core/ext/transport/chttp2/transport/huffsyms.h \
src/core/ext/transport/chttp2/transport/internal.h \
src/core/ext/transport/chttp2/transport/legacy_frame.h \
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc \
src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h \
src/core/ext/transport/chttp2/transport/parsing.cc \
src/core/ext/transport/chttp2/transport/ping_abuse_policy.cc \
src/core/ext/transport/chttp2/transport/ping_abuse_policy.h \
@ -2728,6 +2726,7 @@ src/core/util/posix/string.cc \
src/core/util/posix/sync.cc \
src/core/util/posix/time.cc \
src/core/util/posix/tmpfile.cc \
src/core/util/ring_buffer.h \
src/core/util/spinlock.h \
src/core/util/string.cc \
src/core/util/string.h \

@ -6135,30 +6135,6 @@
],
"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": "max_concurrent_streams_policy_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
@ -9083,6 +9059,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": "ring_buffer_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save