diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000000000000000000000000000000000..60131f2eab114fa480350d6d176169634e4d2613 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,31 @@ +Please answer these questions before submitting your issue. + +### Should this be an issue in the gRPC issue tracker? + +Create new issues for bugs and feature requests. An issue needs to be actionable. General gRPC discussions and usage questions belong to: +- [grpc.io mailing list](https://groups.google.com/forum/#!forum/grpc-io) +- [StackOverflow, with `grpc` tag](http://stackoverflow.com/questions/tagged/grpc) + +*Please don't double post your questions in more locations, we are monitoring both channels and the time spent de-duplicating questions can is better spent answering more user questions.* + +### What version of gRPC and what language are you using? + + +### What operating system (Linux, Windows, …) and version? + + +### What runtime / compiler are you using (e.g. python version or version of gcc) + + +### What did you do? +If possible, provide a recipe for reproducing the error. Try being specific and include code snippets if helpful. + +### What did you expect to see? + + +### What did you see instead? + +Make sure you include information that can help us debug (full error message, exception listing, stack trace, logs). + +### Anything else we should know about your project / environment? + diff --git a/BUILD b/BUILD index 62f0e1d2c5660e4b3cd39d944e46b5f0787cd0a8..09b37f5a116d903a6a2501995ff309b9037cc1b1 100644 --- a/BUILD +++ b/BUILD @@ -35,8 +35,12 @@ exports_files(["LICENSE"]) package(default_visibility = ["//visibility:public"]) -load("//bazel:grpc_build_system.bzl", "grpc_cc_library", - "grpc_proto_plugin", "grpc_cc_libraries") +load( + "//bazel:grpc_build_system.bzl", + "grpc_cc_library", + "grpc_proto_plugin", + "grpc_cc_libraries", +) # This should be updated along with build.yaml g_stands_for = "gregarious" @@ -55,10 +59,19 @@ grpc_cc_library( ) grpc_cc_libraries( - name_list = ["grpc", "grpc_unsecure",], srcs = [ "src/core/lib/surface/init.c", ], + additional_dep_list = [ + [ + "grpc_secure", + "grpc_resolver_dns_ares", + "grpc_lb_policy_grpclb_secure", + "grpc_transport_chttp2_client_secure", + "grpc_transport_chttp2_server_secure", + ], + [], + ], additional_src_list = [ [ "src/core/plugin_registry/grpc_plugin_registry.c", @@ -69,30 +82,24 @@ grpc_cc_libraries( ], ], language = "c", + name_list = [ + "grpc", + "grpc_unsecure", + ], standalone = True, deps = [ "census", "grpc_base", + "grpc_deadline_filter", "grpc_lb_policy_pick_first", "grpc_lb_policy_round_robin", "grpc_load_reporting", "grpc_max_age_filter", + "grpc_message_size_filter", "grpc_resolver_dns_native", "grpc_resolver_sockaddr", "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_server_insecure", - "grpc_message_size_filter", - "grpc_deadline_filter", - ], - additional_dep_list = [ - [ - "grpc_secure", - "grpc_resolver_dns_ares", - "grpc_lb_policy_grpclb_secure", - "grpc_transport_chttp2_client_secure", - "grpc_transport_chttp2_server_secure", - ], - [], ], ) @@ -105,9 +112,9 @@ grpc_cc_library( language = "c", deps = [ "grpc_base", + "grpc_http_filters", "grpc_transport_chttp2_client_secure", "grpc_transport_cronet_client_secure", - "grpc_http_filters", ], ) @@ -373,13 +380,13 @@ grpc_cc_library( hdrs = [ "src/core/lib/profiling/timers.h", "src/core/lib/support/arena.h", + "src/core/lib/support/atomic.h", + "src/core/lib/support/atomic_with_atm.h", + "src/core/lib/support/atomic_with_std.h", "src/core/lib/support/backoff.h", "src/core/lib/support/block_annotate.h", "src/core/lib/support/env.h", "src/core/lib/support/memory.h", - "src/core/lib/support/atomic.h", - "src/core/lib/support/atomic_with_atm.h", - "src/core/lib/support/atomic_with_std.h", "src/core/lib/support/mpscq.h", "src/core/lib/support/murmur_hash.h", "src/core/lib/support/spinlock.h", @@ -443,7 +450,14 @@ grpc_cc_library( ) grpc_cc_library( - name = "grpc_base", + name = "grpc_trace", + srcs = ["src/core/lib/debug/trace.c"], + hdrs = ["src/core/lib/debug/trace.h"], + deps = [":gpr"], +) + +grpc_cc_library( + name = "grpc_base_c", srcs = [ "src/core/lib/channel/channel_args.c", "src/core/lib/channel/channel_stack.c", @@ -454,7 +468,6 @@ grpc_cc_library( "src/core/lib/channel/handshaker_registry.c", "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", - "src/core/lib/debug/trace.c", "src/core/lib/http/format_request.c", "src/core/lib/http/httpcli.c", "src/core/lib/http/parser.c", @@ -465,7 +478,12 @@ grpc_cc_library( "src/core/lib/iomgr/endpoint_pair_uv.c", "src/core/lib/iomgr/endpoint_pair_windows.c", "src/core/lib/iomgr/error.c", - "src/core/lib/iomgr/ev_epoll_linux.c", + "src/core/lib/iomgr/ev_epoll1_linux.c", + "src/core/lib/iomgr/ev_epollsig_linux.c", + "src/core/lib/iomgr/ev_epollex_linux.c", + "src/core/lib/iomgr/is_epollexclusive_available.c", + "src/core/lib/iomgr/ev_epoll_thread_pool_linux.c", + "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_posix.c", "src/core/lib/iomgr/exec_ctx.c", @@ -510,6 +528,7 @@ grpc_cc_library( "src/core/lib/iomgr/tcp_windows.c", "src/core/lib/iomgr/time_averaged_stats.c", "src/core/lib/iomgr/timer_generic.c", + "src/core/lib/iomgr/timer_manager.c", "src/core/lib/iomgr/timer_heap.c", "src/core/lib/iomgr/timer_uv.c", "src/core/lib/iomgr/udp_server.c", @@ -547,7 +566,6 @@ grpc_cc_library( "src/core/lib/surface/completion_queue.c", "src/core/lib/surface/completion_queue_factory.c", "src/core/lib/surface/event_string.c", - "src/core/lib/surface/lame_client.cc", "src/core/lib/surface/metadata_array.c", "src/core/lib/surface/server.c", "src/core/lib/surface/validate_metadata.c", @@ -577,7 +595,6 @@ grpc_cc_library( "src/core/lib/channel/handshaker_registry.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", - "src/core/lib/debug/trace.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", @@ -587,7 +604,13 @@ grpc_cc_library( "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/error_internal.h", - "src/core/lib/iomgr/ev_epoll_linux.h", + "src/core/lib/iomgr/ev_epoll1_linux.h", + "src/core/lib/iomgr/ev_epollsig_linux.h", + "src/core/lib/iomgr/ev_epollex_linux.h", + "src/core/lib/iomgr/is_epollexclusive_available.h", + "src/core/lib/iomgr/sys_epoll_wrapper.h", + "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h", + "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -627,6 +650,7 @@ grpc_cc_library( "src/core/lib/iomgr/time_averaged_stats.h", "src/core/lib/iomgr/timer.h", "src/core/lib/iomgr/timer_generic.h", + "src/core/lib/iomgr/timer_manager.h", "src/core/lib/iomgr/timer_heap.h", "src/core/lib/iomgr/timer_uv.h", "src/core/lib/iomgr/udp_server.h", @@ -693,9 +717,21 @@ grpc_cc_library( deps = [ "gpr_base", "grpc_codegen", + "grpc_trace", ], ) +grpc_cc_library( + name = "grpc_base", + language = "c++", + srcs = [ + "src/core/lib/surface/lame_client.cc", + ], + deps = [ + "grpc_base_c", + ] +) + grpc_cc_library( name = "grpc_client_channel", srcs = [ @@ -791,16 +827,16 @@ grpc_cc_library( grpc_cc_library( name = "grpc_http_filters", - hdrs = [ - "src/core/ext/filters/http/message_compress/message_compress_filter.h", - "src/core/ext/filters/http/client/http_client_filter.h", - "src/core/ext/filters/http/server/http_server_filter.h", - ], srcs = [ - "src/core/ext/filters/http/message_compress/message_compress_filter.c", "src/core/ext/filters/http/client/http_client_filter.c", + "src/core/ext/filters/http/http_filters_plugin.c", + "src/core/ext/filters/http/message_compress/message_compress_filter.c", "src/core/ext/filters/http/server/http_server_filter.c", - "src/core/ext/filters/http/http_filters_plugin.c" + ], + hdrs = [ + "src/core/ext/filters/http/client/http_client_filter.h", + "src/core/ext/filters/http/message_compress/message_compress_filter.h", + "src/core/ext/filters/http/server/http_server_filter.h", ], language = "c", deps = [ @@ -1077,8 +1113,8 @@ grpc_cc_library( language = "c", deps = [ "grpc_base", - "grpc_transport_chttp2_alpn", "grpc_http_filters", + "grpc_transport_chttp2_alpn", ], ) @@ -1230,15 +1266,11 @@ grpc_cc_library( language = "c", deps = [ "gpr", + "grpc_trace", ], ) grpc_cc_libraries( - name_list = ["grpc++_base", "grpc++_base_unsecure"], - additional_dep_list = [ - ["grpc", ], - ["grpc_unsecure", ], - ], srcs = [ "src/cpp/client/channel_cc.cc", "src/cpp/client/client_context.cc", @@ -1273,7 +1305,7 @@ grpc_cc_libraries( "src/cpp/util/status.cc", "src/cpp/util/string_ref.cc", "src/cpp/util/time_cc.cc", - ], + ], hdrs = [ "src/cpp/client/create_channel_internal.h", "src/cpp/common/channel_filter.h", @@ -1282,8 +1314,16 @@ grpc_cc_libraries( "src/cpp/server/health/health.pb.h", "src/cpp/server/thread_pool_interface.h", "src/cpp/thread_manager/thread_manager.h", - ], + ], + additional_dep_list = [ + ["grpc"], + ["grpc_unsecure"], + ], language = "c++", + name_list = [ + "grpc++_base", + "grpc++_base_unsecure", + ], public_hdrs = [ "include/grpc++/alarm.h", "include/grpc++/channel.h", @@ -1332,7 +1372,7 @@ grpc_cc_libraries( "include/grpc++/support/stub_options.h", "include/grpc++/support/sync_stream.h", "include/grpc++/support/time.h", - ], + ], deps = [ "grpc++_codegen_base", ], diff --git a/CMakeLists.txt b/CMakeLists.txt index a9954ed6b010f636682a86c26b68981341e1bf6a..e3cdccb7cd6affd0035aa19d546894dfc5381f75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -347,6 +347,7 @@ add_custom_target(plugins add_custom_target(tools_c DEPENDS + check_epollexclusive gen_hpack_tables gen_legal_metadata_characters gen_percent_encoding_tables @@ -392,7 +393,7 @@ endif() add_dependencies(buildtests_c endpoint_pair_test) add_dependencies(buildtests_c error_test) if(_gRPC_PLATFORM_LINUX) -add_dependencies(buildtests_c ev_epoll_linux_test) +add_dependencies(buildtests_c ev_epollsig_linux_test) endif() add_dependencies(buildtests_c fake_resolver_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -930,7 +931,6 @@ add_library(grpc src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -941,7 +941,11 @@ add_library(grpc src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -951,6 +955,7 @@ add_library(grpc src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -987,6 +992,7 @@ add_library(grpc src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -1041,6 +1047,7 @@ add_library(grpc src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c src/core/ext/transport/chttp2/transport/bin_decoder.c src/core/ext/transport/chttp2/transport/bin_encoder.c @@ -1260,7 +1267,6 @@ add_library(grpc_cronet src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -1271,7 +1277,11 @@ add_library(grpc_cronet src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -1281,6 +1291,7 @@ add_library(grpc_cronet src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -1317,6 +1328,7 @@ add_library(grpc_cronet src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -1371,6 +1383,7 @@ add_library(grpc_cronet src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c src/core/ext/transport/cronet/client/secure/cronet_channel_create.c src/core/ext/transport/cronet/transport/cronet_api_dummy.c src/core/ext/transport/cronet/transport/cronet_transport.c @@ -1571,7 +1584,6 @@ add_library(grpc_test_util src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -1582,7 +1594,11 @@ add_library(grpc_test_util src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -1592,6 +1608,7 @@ add_library(grpc_test_util src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -1628,6 +1645,7 @@ add_library(grpc_test_util src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -1682,6 +1700,7 @@ add_library(grpc_test_util src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c ) if(WIN32 AND MSVC) @@ -1827,7 +1846,6 @@ add_library(grpc_unsecure src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -1838,7 +1856,11 @@ add_library(grpc_unsecure src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -1848,6 +1870,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -1884,6 +1907,7 @@ add_library(grpc_unsecure src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -1938,6 +1962,7 @@ add_library(grpc_unsecure src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c src/core/ext/transport/chttp2/server/insecure/server_chttp2.c src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c src/core/ext/transport/chttp2/transport/bin_decoder.c @@ -2250,7 +2275,6 @@ add_library(grpc++ src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -2261,7 +2285,11 @@ add_library(grpc++ src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -2271,6 +2299,7 @@ add_library(grpc++ src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -2307,6 +2336,7 @@ add_library(grpc++ src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -2361,6 +2391,7 @@ add_library(grpc++ src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c @@ -2575,7 +2606,6 @@ add_library(grpc++_cronet src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -2586,7 +2616,11 @@ add_library(grpc++_cronet src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -2596,6 +2630,7 @@ add_library(grpc++_cronet src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -2632,6 +2667,7 @@ add_library(grpc++_cronet src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -2686,6 +2722,7 @@ add_library(grpc++_cronet src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c @@ -3344,7 +3381,6 @@ add_library(grpc++_unsecure src/core/lib/channel/handshaker_registry.c src/core/lib/compression/compression.c src/core/lib/compression/message_compress.c - src/core/lib/debug/trace.c src/core/lib/http/format_request.c src/core/lib/http/httpcli.c src/core/lib/http/parser.c @@ -3355,7 +3391,11 @@ add_library(grpc++_unsecure src/core/lib/iomgr/endpoint_pair_uv.c src/core/lib/iomgr/endpoint_pair_windows.c src/core/lib/iomgr/error.c - src/core/lib/iomgr/ev_epoll_linux.c + src/core/lib/iomgr/ev_epoll1_linux.c + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + src/core/lib/iomgr/ev_epollex_linux.c + src/core/lib/iomgr/ev_epollsig_linux.c src/core/lib/iomgr/ev_poll_posix.c src/core/lib/iomgr/ev_posix.c src/core/lib/iomgr/exec_ctx.c @@ -3365,6 +3405,7 @@ add_library(grpc++_unsecure src/core/lib/iomgr/iomgr_posix.c src/core/lib/iomgr/iomgr_uv.c src/core/lib/iomgr/iomgr_windows.c + src/core/lib/iomgr/is_epollexclusive_available.c src/core/lib/iomgr/load_file.c src/core/lib/iomgr/lockfree_event.c src/core/lib/iomgr/network_status_tracker.c @@ -3401,6 +3442,7 @@ add_library(grpc++_unsecure src/core/lib/iomgr/time_averaged_stats.c src/core/lib/iomgr/timer_generic.c src/core/lib/iomgr/timer_heap.c + src/core/lib/iomgr/timer_manager.c src/core/lib/iomgr/timer_uv.c src/core/lib/iomgr/udp_server.c src/core/lib/iomgr/unix_sockets_posix.c @@ -3455,6 +3497,7 @@ add_library(grpc++_unsecure src/core/lib/transport/timeout_encoding.c src/core/lib/transport/transport.c src/core/lib/transport/transport_op_string.c + src/core/lib/debug/trace.c third_party/nanopb/pb_common.c third_party/nanopb/pb_decode.c third_party/nanopb/pb_encode.c @@ -4542,6 +4585,7 @@ add_library(end2end_tests test/core/end2end/tests/simple_request.c test/core/end2end/tests/streaming_error_response.c test/core/end2end/tests/trailing_metadata.c + test/core/end2end/tests/workaround_cronet_compression.c test/core/end2end/tests/write_buffering.c test/core/end2end/tests/write_buffering_at_end.c ) @@ -4639,6 +4683,7 @@ add_library(end2end_nosec_tests test/core/end2end/tests/simple_request.c test/core/end2end/tests/streaming_error_response.c test/core/end2end/tests/trailing_metadata.c + test/core/end2end/tests/workaround_cronet_compression.c test/core/end2end/tests/write_buffering.c test/core/end2end/tests/write_buffering_at_end.c ) @@ -5077,6 +5122,42 @@ target_link_libraries(channel_create_test ) endif (gRPC_BUILD_TESTS) + +add_executable(check_epollexclusive + test/build/check_epollexclusive.c +) + + +target_include_directories(check_epollexclusive + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_BUILD_INCLUDE_DIR} + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CARES_PLATFORM_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include +) + +target_link_libraries(check_epollexclusive + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc + gpr +) + + +if (gRPC_INSTALL) + install(TARGETS check_epollexclusive EXPORT gRPCTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) +endif() + if (gRPC_BUILD_TESTS) add_executable(chttp2_hpack_encoder_test @@ -5454,12 +5535,12 @@ endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX) -add_executable(ev_epoll_linux_test - test/core/iomgr/ev_epoll_linux_test.c +add_executable(ev_epollsig_linux_test + test/core/iomgr/ev_epollsig_linux_test.c ) -target_include_directories(ev_epoll_linux_test +target_include_directories(ev_epollsig_linux_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${BORINGSSL_ROOT_DIR}/include @@ -5474,7 +5555,7 @@ target_include_directories(ev_epoll_linux_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include ) -target_link_libraries(ev_epoll_linux_test +target_link_libraries(ev_epollsig_linux_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc diff --git a/INSTALL.md b/INSTALL.md index 6cfa1b6cbaf34ad1c9b6557cf2b75e159ebd611d..5406fec84dbf73f3e474f995670702996a514b8c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -51,6 +51,15 @@ If you plan to build from source and run tests, install the following as well: $ brew install gflags ``` +*Tip*: when building, +you *may* want to explicitly set the `LIBTOOL` and `LIBTOOLIZE` +environment variables when running `make` to ensure the version +installed by `brew` is being used: + +```sh + $ LIBTOOL=glibtool LIBTOOLIZE=glibtoolize make +``` + ## Protoc By default gRPC uses [protocol buffers](https://github.com/google/protobuf), diff --git a/Makefile b/Makefile index 5038f331be72b565558a6328393235dd53b0105f..71e531b02107a860bccdba5eca09f7385c615f51 100644 --- a/Makefile +++ b/Makefile @@ -308,10 +308,6 @@ else TMPOUT = `mktemp /tmp/test-out-XXXXXX` endif -# Detect if we can use C++11 -CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc -HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false) - CHECK_SHADOW_WORKS_CMD = $(CC) -std=c99 -Werror -Wshadow -o $(TMPOUT) -c test/build/shadow.c HAS_WORKING_SHADOW = $(shell $(CHECK_SHADOW_WORKS_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_WORKING_SHADOW),true) @@ -342,11 +338,7 @@ HOST_LD ?= $(LD) HOST_LDXX ?= $(LDXX) CFLAGS += -std=c99 -Wsign-conversion -Wconversion $(W_SHADOW) $(W_EXTRA_SEMI) -ifeq ($(HAS_CXX11),true) CXXFLAGS += -std=c++11 -else -CXXFLAGS += -std=c++0x -endif CPPFLAGS += -g -Wall -Wextra -Werror -Wno-long-long -Wno-unused-parameter -DOSATOMIC_USE_INLINED=1 LDFLAGS += -g @@ -978,6 +970,7 @@ census_context_test: $(BINDIR)/$(CONFIG)/census_context_test census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test +check_epollexclusive: $(BINDIR)/$(CONFIG)/check_epollexclusive chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test chttp2_stream_map_test: $(BINDIR)/$(CONFIG)/chttp2_stream_map_test chttp2_varint_test: $(BINDIR)/$(CONFIG)/chttp2_varint_test @@ -991,7 +984,7 @@ dns_resolver_test: $(BINDIR)/$(CONFIG)/dns_resolver_test dualstack_socket_test: $(BINDIR)/$(CONFIG)/dualstack_socket_test endpoint_pair_test: $(BINDIR)/$(CONFIG)/endpoint_pair_test error_test: $(BINDIR)/$(CONFIG)/error_test -ev_epoll_linux_test: $(BINDIR)/$(CONFIG)/ev_epoll_linux_test +ev_epollsig_linux_test: $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test fake_resolver_test: $(BINDIR)/$(CONFIG)/fake_resolver_test fd_conservation_posix_test: $(BINDIR)/$(CONFIG)/fd_conservation_posix_test fd_posix_test: $(BINDIR)/$(CONFIG)/fd_posix_test @@ -1382,7 +1375,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/dualstack_socket_test \ $(BINDIR)/$(CONFIG)/endpoint_pair_test \ $(BINDIR)/$(CONFIG)/error_test \ - $(BINDIR)/$(CONFIG)/ev_epoll_linux_test \ + $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test \ $(BINDIR)/$(CONFIG)/fake_resolver_test \ $(BINDIR)/$(CONFIG)/fd_conservation_posix_test \ $(BINDIR)/$(CONFIG)/fd_posix_test \ @@ -1800,8 +1793,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/endpoint_pair_test || ( echo test endpoint_pair_test failed ; exit 1 ) $(E) "[RUN] Testing error_test" $(Q) $(BINDIR)/$(CONFIG)/error_test || ( echo test error_test failed ; exit 1 ) - $(E) "[RUN] Testing ev_epoll_linux_test" - $(Q) $(BINDIR)/$(CONFIG)/ev_epoll_linux_test || ( echo test ev_epoll_linux_test failed ; exit 1 ) + $(E) "[RUN] Testing ev_epollsig_linux_test" + $(Q) $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test || ( echo test ev_epollsig_linux_test failed ; exit 1 ) $(E) "[RUN] Testing fake_resolver_test" $(Q) $(BINDIR)/$(CONFIG)/fake_resolver_test || ( echo test fake_resolver_test failed ; exit 1 ) $(E) "[RUN] Testing fd_conservation_posix_test" @@ -2149,7 +2142,7 @@ test_python: static_c tools: tools_c tools_cxx -tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/grpc_verify_jwt +tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/check_epollexclusive $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters $(BINDIR)/$(CONFIG)/gen_percent_encoding_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/grpc_verify_jwt tools_cxx: privatelibs_cxx @@ -2915,7 +2908,6 @@ LIBGRPC_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -2926,7 +2918,11 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -2936,6 +2932,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -2972,6 +2969,7 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -3026,6 +3024,7 @@ LIBGRPC_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ @@ -3243,7 +3242,6 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -3254,7 +3252,11 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3264,6 +3266,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -3300,6 +3303,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -3354,6 +3358,7 @@ LIBGRPC_CRONET_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ src/core/ext/transport/cronet/client/secure/cronet_channel_create.c \ src/core/ext/transport/cronet/transport/cronet_api_dummy.c \ src/core/ext/transport/cronet/transport/cronet_transport.c \ @@ -3553,7 +3558,6 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -3564,7 +3568,11 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3574,6 +3582,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -3610,6 +3619,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -3664,6 +3674,7 @@ LIBGRPC_TEST_UTIL_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ @@ -3781,7 +3792,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -3792,7 +3802,11 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -3802,6 +3816,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -3838,6 +3853,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -3892,6 +3908,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2.c \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ @@ -4181,7 +4198,6 @@ LIBGRPC++_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -4192,7 +4208,11 @@ LIBGRPC++_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -4202,6 +4222,7 @@ LIBGRPC++_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -4238,6 +4259,7 @@ LIBGRPC++_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -4292,6 +4314,7 @@ LIBGRPC++_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -4514,7 +4537,6 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -4525,7 +4547,11 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -4535,6 +4561,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -4571,6 +4598,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -4625,6 +4653,7 @@ LIBGRPC++_CRONET_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -5273,7 +5302,6 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -5284,7 +5312,11 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -5294,6 +5326,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -5330,6 +5363,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -5384,6 +5418,7 @@ LIBGRPC++_UNSECURE_SRC = \ src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ third_party/nanopb/pb_common.c \ third_party/nanopb/pb_decode.c \ third_party/nanopb/pb_encode.c \ @@ -8440,6 +8475,7 @@ LIBEND2END_TESTS_SRC = \ test/core/end2end/tests/simple_request.c \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ + test/core/end2end/tests/workaround_cronet_compression.c \ test/core/end2end/tests/write_buffering.c \ test/core/end2end/tests/write_buffering_at_end.c \ @@ -8532,6 +8568,7 @@ LIBEND2END_NOSEC_TESTS_SRC = \ test/core/end2end/tests/simple_request.c \ test/core/end2end/tests/streaming_error_response.c \ test/core/end2end/tests/trailing_metadata.c \ + test/core/end2end/tests/workaround_cronet_compression.c \ test/core/end2end/tests/write_buffering.c \ test/core/end2end/tests/write_buffering_at_end.c \ @@ -9009,6 +9046,38 @@ endif endif +CHECK_EPOLLEXCLUSIVE_SRC = \ + test/build/check_epollexclusive.c \ + +CHECK_EPOLLEXCLUSIVE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CHECK_EPOLLEXCLUSIVE_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/check_epollexclusive: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/check_epollexclusive: $(CHECK_EPOLLEXCLUSIVE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(CHECK_EPOLLEXCLUSIVE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/check_epollexclusive + +endif + +$(OBJDIR)/$(CONFIG)/test/build/check_epollexclusive.o: $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_check_epollexclusive: $(CHECK_EPOLLEXCLUSIVE_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(CHECK_EPOLLEXCLUSIVE_OBJS:.o=.dep) +endif +endif + + CHTTP2_HPACK_ENCODER_TEST_SRC = \ test/core/transport/chttp2/hpack_encoder_test.c \ @@ -9425,34 +9494,34 @@ endif endif -EV_EPOLL_LINUX_TEST_SRC = \ - test/core/iomgr/ev_epoll_linux_test.c \ +EV_EPOLLSIG_LINUX_TEST_SRC = \ + test/core/iomgr/ev_epollsig_linux_test.c \ -EV_EPOLL_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLL_LINUX_TEST_SRC)))) +EV_EPOLLSIG_LINUX_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(EV_EPOLLSIG_LINUX_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. -$(BINDIR)/$(CONFIG)/ev_epoll_linux_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test: openssl_dep_error else -$(BINDIR)/$(CONFIG)/ev_epoll_linux_test: $(EV_EPOLL_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/ev_epollsig_linux_test: $(EV_EPOLLSIG_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(EV_EPOLL_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ev_epoll_linux_test + $(Q) $(LD) $(LDFLAGS) $(EV_EPOLLSIG_LINUX_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/ev_epollsig_linux_test endif -$(OBJDIR)/$(CONFIG)/test/core/iomgr/ev_epoll_linux_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/core/iomgr/ev_epollsig_linux_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_ev_epoll_linux_test: $(EV_EPOLL_LINUX_TEST_OBJS:.o=.dep) +deps_ev_epollsig_linux_test: $(EV_EPOLLSIG_LINUX_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(EV_EPOLL_LINUX_TEST_OBJS:.o=.dep) +-include $(EV_EPOLLSIG_LINUX_TEST_OBJS:.o=.dep) endif endif diff --git a/binding.gyp b/binding.gyp index f264d64cd186ac67dfb9f9e1a17aba576d7e87be..05ccec5fea9c90a8ec90b6cfd41a722ca850239c 100644 --- a/binding.gyp +++ b/binding.gyp @@ -663,7 +663,6 @@ 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', - 'src/core/lib/debug/trace.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', @@ -674,7 +673,11 @@ 'src/core/lib/iomgr/endpoint_pair_uv.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', 'src/core/lib/iomgr/error.c', - 'src/core/lib/iomgr/ev_epoll_linux.c', + 'src/core/lib/iomgr/ev_epoll1_linux.c', + 'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c', + 'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c', + 'src/core/lib/iomgr/ev_epollex_linux.c', + 'src/core/lib/iomgr/ev_epollsig_linux.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -684,6 +687,7 @@ 'src/core/lib/iomgr/iomgr_posix.c', 'src/core/lib/iomgr/iomgr_uv.c', 'src/core/lib/iomgr/iomgr_windows.c', + 'src/core/lib/iomgr/is_epollexclusive_available.c', 'src/core/lib/iomgr/load_file.c', 'src/core/lib/iomgr/lockfree_event.c', 'src/core/lib/iomgr/network_status_tracker.c', @@ -720,6 +724,7 @@ 'src/core/lib/iomgr/time_averaged_stats.c', 'src/core/lib/iomgr/timer_generic.c', 'src/core/lib/iomgr/timer_heap.c', + 'src/core/lib/iomgr/timer_manager.c', 'src/core/lib/iomgr/timer_uv.c', 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', @@ -774,6 +779,7 @@ 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', + 'src/core/lib/debug/trace.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', 'src/core/ext/transport/chttp2/transport/bin_decoder.c', 'src/core/ext/transport/chttp2/transport/bin_encoder.c', diff --git a/build.yaml b/build.yaml index bf980e65cdf27a142193702fc9f04aac7a144d84..b212c92f7aecb0dc4092a1a81cdd16affb15c09a 100644 --- a/build.yaml +++ b/build.yaml @@ -188,7 +188,6 @@ filegroups: - src/core/lib/channel/handshaker_registry.h - src/core/lib/compression/algorithm_metadata.h - src/core/lib/compression/message_compress.h - - src/core/lib/debug/trace.h - src/core/lib/http/format_request.h - src/core/lib/http/httpcli.h - src/core/lib/http/parser.h @@ -198,7 +197,11 @@ filegroups: - src/core/lib/iomgr/endpoint_pair.h - src/core/lib/iomgr/error.h - src/core/lib/iomgr/error_internal.h - - src/core/lib/iomgr/ev_epoll_linux.h + - src/core/lib/iomgr/ev_epoll1_linux.h + - src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h + - src/core/lib/iomgr/ev_epoll_thread_pool_linux.h + - src/core/lib/iomgr/ev_epollex_linux.h + - src/core/lib/iomgr/ev_epollsig_linux.h - src/core/lib/iomgr/ev_poll_posix.h - src/core/lib/iomgr/ev_posix.h - src/core/lib/iomgr/exec_ctx.h @@ -207,6 +210,7 @@ filegroups: - src/core/lib/iomgr/iomgr.h - src/core/lib/iomgr/iomgr_internal.h - src/core/lib/iomgr/iomgr_posix.h + - src/core/lib/iomgr/is_epollexclusive_available.h - src/core/lib/iomgr/load_file.h - src/core/lib/iomgr/lockfree_event.h - src/core/lib/iomgr/network_status_tracker.h @@ -228,6 +232,7 @@ filegroups: - src/core/lib/iomgr/socket_utils.h - src/core/lib/iomgr/socket_utils_posix.h - src/core/lib/iomgr/socket_windows.h + - src/core/lib/iomgr/sys_epoll_wrapper.h - src/core/lib/iomgr/tcp_client.h - src/core/lib/iomgr/tcp_client_posix.h - src/core/lib/iomgr/tcp_posix.h @@ -239,6 +244,7 @@ filegroups: - src/core/lib/iomgr/timer.h - src/core/lib/iomgr/timer_generic.h - src/core/lib/iomgr/timer_heap.h + - src/core/lib/iomgr/timer_manager.h - src/core/lib/iomgr/timer_uv.h - src/core/lib/iomgr/udp_server.h - src/core/lib/iomgr/unix_sockets_posix.h @@ -294,7 +300,6 @@ filegroups: - src/core/lib/channel/handshaker_registry.c - src/core/lib/compression/compression.c - src/core/lib/compression/message_compress.c - - src/core/lib/debug/trace.c - src/core/lib/http/format_request.c - src/core/lib/http/httpcli.c - src/core/lib/http/parser.c @@ -305,7 +310,11 @@ filegroups: - src/core/lib/iomgr/endpoint_pair_uv.c - src/core/lib/iomgr/endpoint_pair_windows.c - src/core/lib/iomgr/error.c - - src/core/lib/iomgr/ev_epoll_linux.c + - src/core/lib/iomgr/ev_epoll1_linux.c + - src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c + - src/core/lib/iomgr/ev_epoll_thread_pool_linux.c + - src/core/lib/iomgr/ev_epollex_linux.c + - src/core/lib/iomgr/ev_epollsig_linux.c - src/core/lib/iomgr/ev_poll_posix.c - src/core/lib/iomgr/ev_posix.c - src/core/lib/iomgr/exec_ctx.c @@ -315,6 +324,7 @@ filegroups: - src/core/lib/iomgr/iomgr_posix.c - src/core/lib/iomgr/iomgr_uv.c - src/core/lib/iomgr/iomgr_windows.c + - src/core/lib/iomgr/is_epollexclusive_available.c - src/core/lib/iomgr/load_file.c - src/core/lib/iomgr/lockfree_event.c - src/core/lib/iomgr/network_status_tracker.c @@ -351,6 +361,7 @@ filegroups: - src/core/lib/iomgr/time_averaged_stats.c - src/core/lib/iomgr/timer_generic.c - src/core/lib/iomgr/timer_heap.c + - src/core/lib/iomgr/timer_manager.c - src/core/lib/iomgr/timer_uv.c - src/core/lib/iomgr/udp_server.c - src/core/lib/iomgr/unix_sockets_posix.c @@ -409,6 +420,7 @@ filegroups: - gpr uses: - grpc_codegen + - grpc_trace - name: grpc_client_channel headers: - src/core/ext/filters/client_channel/client_channel.h @@ -691,6 +703,13 @@ filegroups: deps: - grpc - gpr_test_util +- name: grpc_trace + headers: + - src/core/lib/debug/trace.h + src: + - src/core/lib/debug/trace.c + deps: + - gpr - name: grpc_transport_chttp2 headers: - src/core/ext/transport/chttp2/transport/bin_decoder.h @@ -848,6 +867,8 @@ filegroups: deps: - gpr secure: true + uses: + - grpc_trace - name: grpc++_base language: c++ public_headers: @@ -1683,6 +1704,14 @@ targets: - grpc - gpr_test_util - gpr +- name: check_epollexclusive + build: tool + language: c + src: + - test/build/check_epollexclusive.c + deps: + - grpc + - gpr - name: chttp2_hpack_encoder_test build: test language: c @@ -1835,12 +1864,12 @@ targets: - grpc - gpr_test_util - gpr -- name: ev_epoll_linux_test +- name: ev_epollsig_linux_test cpu_cost: 3 build: test language: c src: - - test/core/iomgr/ev_epoll_linux_test.c + - test/core/iomgr/ev_epollsig_linux_test.c deps: - grpc_test_util - grpc @@ -4573,6 +4602,7 @@ node_modules: - src/node/src/client.js - src/node/src/common.js - src/node/src/credentials.js + - src/node/src/constants.js - src/node/src/grpc_extension.js - src/node/src/metadata.js - src/node/src/server.js diff --git a/composer.json b/composer.json index 0cafb94808c6887883980495a2f340ee77c158bb..284b57a8098158bed6b57a4d5a473e6fb6021a69 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "license": "BSD-3-Clause", "require": { "php": ">=5.5.0", - "google/protobuf": "^v3.1.0" + "google/protobuf": "^v3.3.0" }, "require-dev": { "google/auth": "v0.9" diff --git a/config.m4 b/config.m4 index ffc565de3d0442af8577bcd73ee00cd23c158ce7..a70284594b35016ef973051c0531e3e7276f688d 100644 --- a/config.m4 +++ b/config.m4 @@ -97,7 +97,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/channel/handshaker_registry.c \ src/core/lib/compression/compression.c \ src/core/lib/compression/message_compress.c \ - src/core/lib/debug/trace.c \ src/core/lib/http/format_request.c \ src/core/lib/http/httpcli.c \ src/core/lib/http/parser.c \ @@ -108,7 +107,11 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/endpoint_pair_uv.c \ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ - src/core/lib/iomgr/ev_epoll_linux.c \ + src/core/lib/iomgr/ev_epoll1_linux.c \ + src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ + src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ + src/core/lib/iomgr/ev_epollex_linux.c \ + src/core/lib/iomgr/ev_epollsig_linux.c \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_posix.c \ src/core/lib/iomgr/exec_ctx.c \ @@ -118,6 +121,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ + src/core/lib/iomgr/is_epollexclusive_available.c \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/lockfree_event.c \ src/core/lib/iomgr/network_status_tracker.c \ @@ -154,6 +158,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/time_averaged_stats.c \ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_heap.c \ + src/core/lib/iomgr/timer_manager.c \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/udp_server.c \ src/core/lib/iomgr/unix_sockets_posix.c \ @@ -208,6 +213,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/transport/timeout_encoding.c \ src/core/lib/transport/transport.c \ src/core/lib/transport/transport_op_string.c \ + src/core/lib/debug/trace.c \ src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c \ src/core/ext/transport/chttp2/transport/bin_decoder.c \ src/core/ext/transport/chttp2/transport/bin_encoder.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 0c382477147f41a3a72060f5132369a635e3962f..3915d5ae4e29cba8aba0a64c09be9b27311227ac 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -270,7 +270,6 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker_registry.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', - 'src/core/lib/debug/trace.h', 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', @@ -280,7 +279,11 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/error_internal.h', - 'src/core/lib/iomgr/ev_epoll_linux.h', + 'src/core/lib/iomgr/ev_epoll1_linux.h', + 'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h', + 'src/core/lib/iomgr/ev_epoll_thread_pool_linux.h', + 'src/core/lib/iomgr/ev_epollex_linux.h', + 'src/core/lib/iomgr/ev_epollsig_linux.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -289,6 +292,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_internal.h', 'src/core/lib/iomgr/iomgr_posix.h', + 'src/core/lib/iomgr/is_epollexclusive_available.h', 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/network_status_tracker.h', @@ -310,6 +314,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/socket_utils.h', 'src/core/lib/iomgr/socket_utils_posix.h', 'src/core/lib/iomgr/socket_windows.h', + 'src/core/lib/iomgr/sys_epoll_wrapper.h', 'src/core/lib/iomgr/tcp_client.h', 'src/core/lib/iomgr/tcp_client_posix.h', 'src/core/lib/iomgr/tcp_posix.h', @@ -321,6 +326,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/timer.h', 'src/core/lib/iomgr/timer_generic.h', 'src/core/lib/iomgr/timer_heap.h', + 'src/core/lib/iomgr/timer_manager.h', 'src/core/lib/iomgr/timer_uv.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', @@ -366,6 +372,7 @@ Pod::Spec.new do |s| 'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport_impl.h', + 'src/core/lib/debug/trace.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', 'src/core/ext/transport/chttp2/transport/bin_encoder.h', 'src/core/ext/transport/chttp2/transport/chttp2_transport.h', @@ -479,7 +486,6 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', - 'src/core/lib/debug/trace.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', @@ -490,7 +496,11 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/endpoint_pair_uv.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', 'src/core/lib/iomgr/error.c', - 'src/core/lib/iomgr/ev_epoll_linux.c', + 'src/core/lib/iomgr/ev_epoll1_linux.c', + 'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c', + 'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c', + 'src/core/lib/iomgr/ev_epollex_linux.c', + 'src/core/lib/iomgr/ev_epollsig_linux.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -500,6 +510,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/iomgr_posix.c', 'src/core/lib/iomgr/iomgr_uv.c', 'src/core/lib/iomgr/iomgr_windows.c', + 'src/core/lib/iomgr/is_epollexclusive_available.c', 'src/core/lib/iomgr/load_file.c', 'src/core/lib/iomgr/lockfree_event.c', 'src/core/lib/iomgr/network_status_tracker.c', @@ -536,6 +547,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/time_averaged_stats.c', 'src/core/lib/iomgr/timer_generic.c', 'src/core/lib/iomgr/timer_heap.c', + 'src/core/lib/iomgr/timer_manager.c', 'src/core/lib/iomgr/timer_uv.c', 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', @@ -590,6 +602,7 @@ Pod::Spec.new do |s| 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', + 'src/core/lib/debug/trace.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', 'src/core/ext/transport/chttp2/transport/bin_decoder.c', 'src/core/ext/transport/chttp2/transport/bin_encoder.c', @@ -739,7 +752,6 @@ Pod::Spec.new do |s| 'src/core/lib/channel/handshaker_registry.h', 'src/core/lib/compression/algorithm_metadata.h', 'src/core/lib/compression/message_compress.h', - 'src/core/lib/debug/trace.h', 'src/core/lib/http/format_request.h', 'src/core/lib/http/httpcli.h', 'src/core/lib/http/parser.h', @@ -749,7 +761,11 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/endpoint_pair.h', 'src/core/lib/iomgr/error.h', 'src/core/lib/iomgr/error_internal.h', - 'src/core/lib/iomgr/ev_epoll_linux.h', + 'src/core/lib/iomgr/ev_epoll1_linux.h', + 'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h', + 'src/core/lib/iomgr/ev_epoll_thread_pool_linux.h', + 'src/core/lib/iomgr/ev_epollex_linux.h', + 'src/core/lib/iomgr/ev_epollsig_linux.h', 'src/core/lib/iomgr/ev_poll_posix.h', 'src/core/lib/iomgr/ev_posix.h', 'src/core/lib/iomgr/exec_ctx.h', @@ -758,6 +774,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/iomgr.h', 'src/core/lib/iomgr/iomgr_internal.h', 'src/core/lib/iomgr/iomgr_posix.h', + 'src/core/lib/iomgr/is_epollexclusive_available.h', 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/network_status_tracker.h', @@ -779,6 +796,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/socket_utils.h', 'src/core/lib/iomgr/socket_utils_posix.h', 'src/core/lib/iomgr/socket_windows.h', + 'src/core/lib/iomgr/sys_epoll_wrapper.h', 'src/core/lib/iomgr/tcp_client.h', 'src/core/lib/iomgr/tcp_client_posix.h', 'src/core/lib/iomgr/tcp_posix.h', @@ -790,6 +808,7 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/timer.h', 'src/core/lib/iomgr/timer_generic.h', 'src/core/lib/iomgr/timer_heap.h', + 'src/core/lib/iomgr/timer_manager.h', 'src/core/lib/iomgr/timer_uv.h', 'src/core/lib/iomgr/udp_server.h', 'src/core/lib/iomgr/unix_sockets_posix.h', @@ -835,6 +854,7 @@ Pod::Spec.new do |s| 'src/core/lib/transport/timeout_encoding.h', 'src/core/lib/transport/transport.h', 'src/core/lib/transport/transport_impl.h', + 'src/core/lib/debug/trace.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', 'src/core/ext/transport/chttp2/transport/bin_encoder.h', 'src/core/ext/transport/chttp2/transport/chttp2_transport.h', diff --git a/grpc.gemspec b/grpc.gemspec index a0244e01629cea8ebdd08a54c74121be9449ef51..8de816c58fd1f9a718ba0a03b666a72192441f30 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -186,7 +186,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/handshaker_registry.h ) s.files += %w( src/core/lib/compression/algorithm_metadata.h ) s.files += %w( src/core/lib/compression/message_compress.h ) - s.files += %w( src/core/lib/debug/trace.h ) s.files += %w( src/core/lib/http/format_request.h ) s.files += %w( src/core/lib/http/httpcli.h ) s.files += %w( src/core/lib/http/parser.h ) @@ -196,7 +195,11 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/endpoint_pair.h ) s.files += %w( src/core/lib/iomgr/error.h ) s.files += %w( src/core/lib/iomgr/error_internal.h ) - s.files += %w( src/core/lib/iomgr/ev_epoll_linux.h ) + s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.h ) + s.files += %w( src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h ) + s.files += %w( src/core/lib/iomgr/ev_epoll_thread_pool_linux.h ) + s.files += %w( src/core/lib/iomgr/ev_epollex_linux.h ) + s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.h ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.h ) s.files += %w( src/core/lib/iomgr/ev_posix.h ) s.files += %w( src/core/lib/iomgr/exec_ctx.h ) @@ -205,6 +208,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/iomgr.h ) s.files += %w( src/core/lib/iomgr/iomgr_internal.h ) s.files += %w( src/core/lib/iomgr/iomgr_posix.h ) + s.files += %w( src/core/lib/iomgr/is_epollexclusive_available.h ) s.files += %w( src/core/lib/iomgr/load_file.h ) s.files += %w( src/core/lib/iomgr/lockfree_event.h ) s.files += %w( src/core/lib/iomgr/network_status_tracker.h ) @@ -226,6 +230,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/socket_utils.h ) s.files += %w( src/core/lib/iomgr/socket_utils_posix.h ) s.files += %w( src/core/lib/iomgr/socket_windows.h ) + s.files += %w( src/core/lib/iomgr/sys_epoll_wrapper.h ) s.files += %w( src/core/lib/iomgr/tcp_client.h ) s.files += %w( src/core/lib/iomgr/tcp_client_posix.h ) s.files += %w( src/core/lib/iomgr/tcp_posix.h ) @@ -237,6 +242,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/timer.h ) s.files += %w( src/core/lib/iomgr/timer_generic.h ) s.files += %w( src/core/lib/iomgr/timer_heap.h ) + s.files += %w( src/core/lib/iomgr/timer_manager.h ) s.files += %w( src/core/lib/iomgr/timer_uv.h ) s.files += %w( src/core/lib/iomgr/udp_server.h ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.h ) @@ -282,6 +288,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/transport/timeout_encoding.h ) s.files += %w( src/core/lib/transport/transport.h ) s.files += %w( src/core/lib/transport/transport_impl.h ) + s.files += %w( src/core/lib/debug/trace.h ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.h ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.h ) s.files += %w( src/core/ext/transport/chttp2/transport/chttp2_transport.h ) @@ -395,7 +402,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/channel/handshaker_registry.c ) s.files += %w( src/core/lib/compression/compression.c ) s.files += %w( src/core/lib/compression/message_compress.c ) - s.files += %w( src/core/lib/debug/trace.c ) s.files += %w( src/core/lib/http/format_request.c ) s.files += %w( src/core/lib/http/httpcli.c ) s.files += %w( src/core/lib/http/parser.c ) @@ -406,7 +412,11 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/endpoint_pair_uv.c ) s.files += %w( src/core/lib/iomgr/endpoint_pair_windows.c ) s.files += %w( src/core/lib/iomgr/error.c ) - s.files += %w( src/core/lib/iomgr/ev_epoll_linux.c ) + s.files += %w( src/core/lib/iomgr/ev_epoll1_linux.c ) + s.files += %w( src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c ) + s.files += %w( src/core/lib/iomgr/ev_epoll_thread_pool_linux.c ) + s.files += %w( src/core/lib/iomgr/ev_epollex_linux.c ) + s.files += %w( src/core/lib/iomgr/ev_epollsig_linux.c ) s.files += %w( src/core/lib/iomgr/ev_poll_posix.c ) s.files += %w( src/core/lib/iomgr/ev_posix.c ) s.files += %w( src/core/lib/iomgr/exec_ctx.c ) @@ -416,6 +426,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/iomgr_posix.c ) s.files += %w( src/core/lib/iomgr/iomgr_uv.c ) s.files += %w( src/core/lib/iomgr/iomgr_windows.c ) + s.files += %w( src/core/lib/iomgr/is_epollexclusive_available.c ) s.files += %w( src/core/lib/iomgr/load_file.c ) s.files += %w( src/core/lib/iomgr/lockfree_event.c ) s.files += %w( src/core/lib/iomgr/network_status_tracker.c ) @@ -452,6 +463,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/time_averaged_stats.c ) s.files += %w( src/core/lib/iomgr/timer_generic.c ) s.files += %w( src/core/lib/iomgr/timer_heap.c ) + s.files += %w( src/core/lib/iomgr/timer_manager.c ) s.files += %w( src/core/lib/iomgr/timer_uv.c ) s.files += %w( src/core/lib/iomgr/udp_server.c ) s.files += %w( src/core/lib/iomgr/unix_sockets_posix.c ) @@ -506,6 +518,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/transport/timeout_encoding.c ) s.files += %w( src/core/lib/transport/transport.c ) s.files += %w( src/core/lib/transport/transport_op_string.c ) + s.files += %w( src/core/lib/debug/trace.c ) s.files += %w( src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_decoder.c ) s.files += %w( src/core/ext/transport/chttp2/transport/bin_encoder.c ) diff --git a/include/grpc++/impl/codegen/config_protobuf.h b/include/grpc++/impl/codegen/config_protobuf.h index 8620d4b2183bfc00b7ab555e6cf43dcfd37bffcf..e66189f8d127db128c34cb7fc9222a067f2a880f 100644 --- a/include/grpc++/impl/codegen/config_protobuf.h +++ b/include/grpc++/impl/codegen/config_protobuf.h @@ -34,6 +34,8 @@ #ifndef GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H #define GRPCXX_IMPL_CODEGEN_CONFIG_PROTOBUF_H +#define GRPC_OPEN_SOURCE_PROTO + #ifndef GRPC_CUSTOM_PROTOBUF_INT64 #include <google/protobuf/stubs/common.h> #define GRPC_CUSTOM_PROTOBUF_INT64 ::google::protobuf::int64 diff --git a/include/grpc++/impl/codegen/core_codegen.h b/include/grpc++/impl/codegen/core_codegen.h index a1593729ebc81368deaeaee4b35f2c26cbc79714..7a1236a716be8c6823a08a4013396c5947bc2af1 100644 --- a/include/grpc++/impl/codegen/core_codegen.h +++ b/include/grpc++/impl/codegen/core_codegen.h @@ -90,11 +90,15 @@ class CoreCodegen final : public CoreCodegenInterface { grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice, size_t nslices) override; - + grpc_slice grpc_slice_new_with_user_data(void* p, size_t len, + void (*destroy)(void*), + void* user_data) override; grpc_slice grpc_empty_slice() override; grpc_slice grpc_slice_malloc(size_t length) override; void grpc_slice_unref(grpc_slice slice) override; + grpc_slice grpc_slice_ref(grpc_slice slice) override; grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override; + grpc_slice grpc_slice_split_head(grpc_slice* s, size_t split) override; void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override; void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override; grpc_slice grpc_slice_from_static_buffer(const void* buffer, diff --git a/include/grpc++/impl/codegen/core_codegen_interface.h b/include/grpc++/impl/codegen/core_codegen_interface.h index 7cc3a824761cb26be1677fa6c11adb52b6f7b07e..4ac37f52559d542eedd039eeb7b7440d7750fe9e 100644 --- a/include/grpc++/impl/codegen/core_codegen_interface.h +++ b/include/grpc++/impl/codegen/core_codegen_interface.h @@ -101,15 +101,18 @@ class CoreCodegenInterface { virtual grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice, size_t nslices) = 0; - + virtual grpc_slice grpc_slice_new_with_user_data(void* p, size_t len, + void (*destroy)(void*), + void* user_data) = 0; virtual void grpc_call_ref(grpc_call* call) = 0; virtual void grpc_call_unref(grpc_call* call) = 0; virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) = 0; - virtual grpc_slice grpc_empty_slice() = 0; virtual grpc_slice grpc_slice_malloc(size_t length) = 0; virtual void grpc_slice_unref(grpc_slice slice) = 0; + virtual grpc_slice grpc_slice_ref(grpc_slice slice) = 0; virtual grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) = 0; + virtual grpc_slice grpc_slice_split_head(grpc_slice* s, size_t split) = 0; virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) = 0; virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0; diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h index 8c0c32bfc5d9bf757f769851d471a6f2f051c5c3..5cdb2a7a155edfe9b641f451ab9d609cdfbb17c2 100644 --- a/include/grpc++/impl/codegen/proto_utils.h +++ b/include/grpc++/impl/codegen/proto_utils.h @@ -54,8 +54,7 @@ class GrpcBufferWriterPeer; const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024; -class GrpcBufferWriter final - : public ::grpc::protobuf::io::ZeroCopyOutputStream { +class GrpcBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream { public: explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size) : block_size_(block_size), byte_count_(0), have_backup_(false) { @@ -103,6 +102,8 @@ class GrpcBufferWriter final grpc::protobuf::int64 ByteCount() const override { return byte_count_; } + grpc_slice_buffer* SliceBuffer() { return slice_buffer_; } + private: friend class GrpcBufferWriterPeer; const int block_size_; @@ -113,8 +114,7 @@ class GrpcBufferWriter final grpc_slice slice_; }; -class GrpcBufferReader final - : public ::grpc::protobuf::io::ZeroCopyInputStream { +class GrpcBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream { public: explicit GrpcBufferReader(grpc_byte_buffer* buffer) : byte_count_(0), backup_count_(0), status_() { @@ -175,64 +175,91 @@ class GrpcBufferReader final return byte_count_ - backup_count_; } - private: + protected: int64_t byte_count_; int64_t backup_count_; grpc_byte_buffer_reader reader_; grpc_slice slice_; Status status_; }; + +template <class BufferWriter, class T> +Status GenericSerialize(const grpc::protobuf::Message& msg, + grpc_byte_buffer** bp, bool* own_buffer) { + static_assert( + std::is_base_of<protobuf::io::ZeroCopyOutputStream, BufferWriter>::value, + "BufferWriter must be a subclass of io::ZeroCopyOutputStream"); + *own_buffer = true; + int byte_size = msg.ByteSize(); + if (byte_size <= internal::kGrpcBufferWriterMaxBufferLength) { + grpc_slice slice = g_core_codegen_interface->grpc_slice_malloc(byte_size); + GPR_CODEGEN_ASSERT( + GRPC_SLICE_END_PTR(slice) == + msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice))); + *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1); + g_core_codegen_interface->grpc_slice_unref(slice); + return g_core_codegen_interface->ok(); + } else { + BufferWriter writer(bp, internal::kGrpcBufferWriterMaxBufferLength); + return msg.SerializeToZeroCopyStream(&writer) + ? g_core_codegen_interface->ok() + : Status(StatusCode::INTERNAL, "Failed to serialize message"); + } +} + +template <class BufferReader, class T> +Status GenericDeserialize(grpc_byte_buffer* buffer, + grpc::protobuf::Message* msg) { + static_assert( + std::is_base_of<protobuf::io::ZeroCopyInputStream, BufferReader>::value, + "BufferReader must be a subclass of io::ZeroCopyInputStream"); + if (buffer == nullptr) { + return Status(StatusCode::INTERNAL, "No payload"); + } + Status result = g_core_codegen_interface->ok(); + { + BufferReader reader(buffer); + if (!reader.status().ok()) { + return reader.status(); + } + ::grpc::protobuf::io::CodedInputStream decoder(&reader); + decoder.SetTotalBytesLimit(INT_MAX, INT_MAX); + if (!msg->ParseFromCodedStream(&decoder)) { + result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); + } + if (!decoder.ConsumedEntireMessage()) { + result = Status(StatusCode::INTERNAL, "Did not read entire message"); + } + } + g_core_codegen_interface->grpc_byte_buffer_destroy(buffer); + return result; +} + } // namespace internal +// this is needed so the following class does not conflict with protobuf +// serializers that utilize internal-only tools. +#ifdef GRPC_OPEN_SOURCE_PROTO +// This class provides a protobuf serializer. It translates between protobuf +// objects and grpc_byte_buffers. More information about SerializationTraits can +// be found in include/grpc++/impl/codegen/serialization_traits.h. template <class T> class SerializationTraits<T, typename std::enable_if<std::is_base_of< grpc::protobuf::Message, T>::value>::type> { public: static Status Serialize(const grpc::protobuf::Message& msg, grpc_byte_buffer** bp, bool* own_buffer) { - *own_buffer = true; - int byte_size = msg.ByteSize(); - if (byte_size <= internal::kGrpcBufferWriterMaxBufferLength) { - grpc_slice slice = g_core_codegen_interface->grpc_slice_malloc(byte_size); - GPR_CODEGEN_ASSERT( - GRPC_SLICE_END_PTR(slice) == - msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice))); - *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1); - g_core_codegen_interface->grpc_slice_unref(slice); - return g_core_codegen_interface->ok(); - } else { - internal::GrpcBufferWriter writer( - bp, internal::kGrpcBufferWriterMaxBufferLength); - return msg.SerializeToZeroCopyStream(&writer) - ? g_core_codegen_interface->ok() - : Status(StatusCode::INTERNAL, "Failed to serialize message"); - } + return internal::GenericSerialize<internal::GrpcBufferWriter, T>( + msg, bp, own_buffer); } static Status Deserialize(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg) { - if (buffer == nullptr) { - return Status(StatusCode::INTERNAL, "No payload"); - } - Status result = g_core_codegen_interface->ok(); - { - internal::GrpcBufferReader reader(buffer); - if (!reader.status().ok()) { - return reader.status(); - } - ::grpc::protobuf::io::CodedInputStream decoder(&reader); - decoder.SetTotalBytesLimit(INT_MAX, INT_MAX); - if (!msg->ParseFromCodedStream(&decoder)) { - result = Status(StatusCode::INTERNAL, msg->InitializationErrorString()); - } - if (!decoder.ConsumedEntireMessage()) { - result = Status(StatusCode::INTERNAL, "Did not read entire message"); - } - } - g_core_codegen_interface->grpc_byte_buffer_destroy(buffer); - return result; + return internal::GenericDeserialize<internal::GrpcBufferReader, T>(buffer, + msg); } }; +#endif } // namespace grpc diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index ca9ea1bcfc40b96009e00e9e819e3700063d67ea..2dcd0701a2b23ba9ab13663382483a09a2eafd4b 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -200,7 +200,10 @@ class ServerBuilder { struct SyncServerSettings { SyncServerSettings() - : num_cqs(1), min_pollers(1), max_pollers(2), cq_timeout_msec(10000) {} + : num_cqs(gpr_cpu_num_cores()), + min_pollers(1), + max_pollers(2), + cq_timeout_msec(10000) {} // Number of server completion queues to create to listen to incoming RPCs. int num_cqs; diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 37452e24c59b6d54014c7e6dcb17a05bc1eaaa43..7d153740e30e42ad4bbe728ffa447bc537843762 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -297,7 +297,8 @@ each time recvmsg (or equivalent) is called */ If 0 or unset, the balancer calls will have no deadline. */ #define GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS "grpc.grpclb_timeout_ms" /** If non-zero, grpc server's cronet compression workaround will be enabled */ -#define GRPC_ARG_WORKAROUND_CRONET_COMPRESSION "grpc.workaround.cronet_compression" +#define GRPC_ARG_WORKAROUND_CRONET_COMPRESSION \ + "grpc.workaround.cronet_compression" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a diff --git a/include/grpc/support/workaround_list.h b/include/grpc/support/workaround_list.h index dceaa5f8978af9f08346efe9e676435d722e4948..6a8aa1f9550171bc421201d235ba7b0aee78e94c 100644 --- a/include/grpc/support/workaround_list.h +++ b/include/grpc/support/workaround_list.h @@ -31,6 +31,9 @@ * */ +#ifndef GRPC_SUPPORT_WORKAROUND_LIST_H +#define GRPC_SUPPORT_WORKAROUND_LIST_H + /* The list of IDs of server workarounds currently maintained by gRPC. For * explanation and detailed descriptions of workarounds, see * /docs/workarounds.md @@ -39,3 +42,5 @@ typedef enum { GRPC_WORKAROUND_ID_CRONET_COMPRESSION = 0, GRPC_MAX_WORKAROUND_ID } grpc_workaround_list; + +#endif diff --git a/package.xml b/package.xml index d6e25d490634a0f626e92ca3dff15a0e55b8a096..32b61380be1c7db9f7b55fc77d7b824d4f36bc39 100644 --- a/package.xml +++ b/package.xml @@ -195,7 +195,6 @@ <file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" /> - <file baseinstalldir="/" name="src/core/lib/debug/trace.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/format_request.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/httpcli.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/parser.h" role="src" /> @@ -205,7 +204,11 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/error.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/error_internal.h" role="src" /> - <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_linux.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_thread_pool_linux.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.h" role="src" /> @@ -214,6 +217,7 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_internal.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/is_epollexclusive_available.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/load_file.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/lockfree_event.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/network_status_tracker.h" role="src" /> @@ -235,6 +239,7 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/socket_utils_posix.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/socket_windows.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/sys_epoll_wrapper.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_client.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_client_posix.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/tcp_posix.h" role="src" /> @@ -246,6 +251,7 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/timer.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/timer_generic.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/timer_heap.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/timer_manager.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/timer_uv.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/udp_server.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix.h" role="src" /> @@ -291,6 +297,7 @@ <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.h" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport_impl.h" role="src" /> + <file baseinstalldir="/" name="src/core/lib/debug/trace.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_decoder.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/chttp2_transport.h" role="src" /> @@ -404,7 +411,6 @@ <file baseinstalldir="/" name="src/core/lib/channel/handshaker_registry.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/compression.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" /> - <file baseinstalldir="/" name="src/core/lib/debug/trace.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/format_request.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/httpcli.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/http/parser.c" role="src" /> @@ -415,7 +421,11 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_uv.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/endpoint_pair_windows.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/error.c" role="src" /> - <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_linux.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll1_linux.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epoll_thread_pool_linux.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollex_linux.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/ev_epollsig_linux.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_poll_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/ev_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/exec_ctx.c" role="src" /> @@ -425,6 +435,7 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_uv.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/iomgr_windows.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/is_epollexclusive_available.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/load_file.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/lockfree_event.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/network_status_tracker.c" role="src" /> @@ -461,6 +472,7 @@ <file baseinstalldir="/" name="src/core/lib/iomgr/time_averaged_stats.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/timer_generic.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/timer_heap.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/iomgr/timer_manager.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/timer_uv.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/udp_server.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/iomgr/unix_sockets_posix.c" role="src" /> @@ -515,6 +527,7 @@ <file baseinstalldir="/" name="src/core/lib/transport/timeout_encoding.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/transport/transport_op_string.c" role="src" /> + <file baseinstalldir="/" name="src/core/lib/debug/trace.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_decoder.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/transport/chttp2/transport/bin_encoder.c" role="src" /> diff --git a/setup.py b/setup.py index 18ba802fb0f8762777b128546a5b4156e10b7179..cb852735f0ff5fe503d5e81edca1ba876d0b325b 100644 --- a/setup.py +++ b/setup.py @@ -116,7 +116,7 @@ if EXTRA_ENV_COMPILE_ARGS is None: elif 'win32' in sys.platform: EXTRA_ENV_COMPILE_ARGS += ' -D_PYTHON_MSVC' elif "linux" in sys.platform: - EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -fvisibility=hidden -fno-wrapv' + EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv' elif "darwin" in sys.platform: EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv' @@ -237,7 +237,7 @@ INSTALL_REQUIRES = ( 'six>=1.5.2', # TODO(atash): eventually split the grpcio package into a metapackage # depending on protobuf and the runtime component (independent of protobuf) - 'protobuf>=3.2.0', + 'protobuf>=3.3.0', ) if not PY3: diff --git a/src/boringssl/gen_build_yaml.py b/src/boringssl/gen_build_yaml.py index c53beb0da5f033f1b801859aead49bd6d6a264c0..d01c2b4ec55a1542a5e53330627b4baa963dc198 100755 --- a/src/boringssl/gen_build_yaml.py +++ b/src/boringssl/gen_build_yaml.py @@ -138,7 +138,7 @@ class Grpc(object): { 'name': 'boringssl_%s' % os.path.basename(test[0]), 'args': [map_testarg(arg) for arg in test[1:]], - 'exclude_configs': ['asan'], + 'exclude_configs': ['asan', 'ubsan'], 'ci_platforms': ['linux', 'mac', 'posix', 'windows'], 'platforms': ['linux', 'mac', 'posix', 'windows'], 'flaky': False, diff --git a/src/core/ext/filters/client_channel/channel_connectivity.c b/src/core/ext/filters/client_channel/channel_connectivity.c index 62f58fb278a2f71d40e1ab8fe12fffadc9ed9ddf..f83670db82efde290c2e51c6b2f979086a8c50e2 100644 --- a/src/core/ext/filters/client_channel/channel_connectivity.c +++ b/src/core/ext/filters/client_channel/channel_connectivity.c @@ -132,7 +132,7 @@ static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w, gpr_mu_lock(&w->mu); if (due_to_completion) { - if (grpc_trace_operation_failures) { + if (GRPC_TRACER_ON(grpc_trace_operation_failures)) { GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error)); } GRPC_ERROR_UNREF(error); diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c index 695be4fdf27ed9867b14a7ebf5a448655bdd6dea..b7c0e929b7e025c6e949c4dce9efa5614010c406 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c @@ -137,7 +137,7 @@ #define GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS 120 #define GRPC_GRPCLB_RECONNECT_JITTER 0.2 -int grpc_lb_glb_trace = 0; +grpc_tracer_flag grpc_lb_glb_trace = GRPC_TRACER_INITIALIZER(false); /* add lb_token of selected subchannel (address) to the call's initial * metadata */ @@ -223,7 +223,7 @@ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg, } else { grpc_grpclb_client_stats_unref(wc_arg->client_stats); } - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy); } GRPC_LB_POLICY_UNREF(exec_ctx, wc_arg->rr_policy, "wrapped_rr_closure"); @@ -574,7 +574,7 @@ static bool update_lb_connectivity_status_locked( GPR_ASSERT(new_rr_state_error == GRPC_ERROR_NONE); } - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Setting grpclb's state to %s from new RR policy %p state.", grpc_connectivity_state_name(new_rr_state), @@ -599,7 +599,7 @@ static bool pick_from_internal_rr_locked( (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure); if (pick_done) { /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */ - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Unreffing RR (0x%" PRIxPTR ")", (intptr_t)wc_arg->rr_policy); } @@ -685,7 +685,7 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx, if (!replace_old_rr) { /* dispose of the new RR policy that won't be used after all */ GRPC_LB_POLICY_UNREF(exec_ctx, new_rr_policy, "rr_handover_no_replace"); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Keeping old RR policy (%p) despite new serverlist: new RR " "policy was in %s connectivity state.", @@ -695,7 +695,7 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx, return; } - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Created RR policy (%p) to replace old RR (%p)", (void *)new_rr_policy, (void *)glb_policy->rr_policy); } @@ -740,7 +740,7 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx, pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy; pp->wrapped_on_complete_arg.client_stats = grpc_grpclb_client_stats_ref(glb_policy->client_stats); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "", (intptr_t)glb_policy->rr_policy); } @@ -754,7 +754,7 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx, glb_policy->pending_pings = pping->next; GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_ping"); pping->wrapped_notify_arg.rr_policy = glb_policy->rr_policy; - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Pending ping about to PING from 0x%" PRIxPTR "", (intptr_t)glb_policy->rr_policy); } @@ -907,7 +907,7 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, GPR_ASSERT(uri->path[0] != '\0'); glb_policy->server_name = gpr_strdup(uri->path[0] == '/' ? uri->path + 1 : uri->path); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Will use '%s' as the server name for LB request.", glb_policy->server_name); } @@ -1095,7 +1095,7 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, bool pick_done; if (glb_policy->rr_policy != NULL) { - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "grpclb %p about to PICK from RR %p", (void *)glb_policy, (void *)glb_policy->rr_policy); } @@ -1118,7 +1118,7 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pick_done = pick_from_internal_rr_locked(exec_ctx, glb_policy->rr_policy, pick_args, target, wc_arg); } else { - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_DEBUG, "No RR policy in grpclb instance %p. Adding to grpclb's pending " "picks", @@ -1355,7 +1355,7 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx, lb_call_init_locked(exec_ctx, glb_policy); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Query for backends (grpclb: %p, lb_call: %p)", (void *)glb_policy, (void *)glb_policy->lb_call); } @@ -1461,7 +1461,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, gpr_time_max(gpr_time_from_seconds(1, GPR_TIMESPAN), grpc_grpclb_duration_to_timespec( &response->client_stats_report_interval)); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "received initial LB response message; " "client load reporting interval = %" PRId64 ".%09d sec", @@ -1474,7 +1474,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, glb_policy->client_load_report_timer_pending = true; GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "client_load_report"); schedule_next_client_load_report(exec_ctx, glb_policy); - } else if (grpc_lb_glb_trace) { + } else if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "received initial LB response message; " "client load reporting NOT enabled"); @@ -1486,7 +1486,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_grpclb_response_parse_serverlist(response_slice); if (serverlist != NULL) { GPR_ASSERT(glb_policy->lb_call != NULL); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Serverlist with %lu servers received", (unsigned long)serverlist->num_servers); for (size_t i = 0; i < serverlist->num_servers; ++i) { @@ -1503,7 +1503,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, if (serverlist->num_servers > 0) { if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) { - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Incoming server list identical to current, ignoring."); } @@ -1521,7 +1521,7 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, rr_handover_locked(exec_ctx, glb_policy); } } else { - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Received empty server list. Picks will stay pending until " "a response with > 0 servers is received"); @@ -1563,7 +1563,7 @@ static void lb_call_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg, glb_lb_policy *glb_policy = arg; if (!glb_policy->shutting_down) { - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_INFO, "Restaring call to LB server (grpclb %p)", (void *)glb_policy); } @@ -1580,7 +1580,7 @@ static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx, GPR_ASSERT(glb_policy->lb_call != NULL); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { char *status_details = grpc_slice_to_c_string(glb_policy->lb_call_status_details); gpr_log(GPR_DEBUG, @@ -1599,7 +1599,7 @@ static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx, gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec next_try = gpr_backoff_step(&glb_policy->lb_call_backoff_state, now); - if (grpc_lb_glb_trace) { + if (GRPC_TRACER_ON(grpc_lb_glb_trace)) { gpr_log(GPR_DEBUG, "Connection to LB server lost (grpclb: %p)...", (void *)glb_policy); gpr_timespec timeout = gpr_time_sub(next_try, now); diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c index 4c17f9c08284c16b24ab6eb3f50e62ed9e0670b2..6e7f4106358e109536d576137781447223ff82d4 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c @@ -74,7 +74,7 @@ typedef struct round_robin_lb_policy round_robin_lb_policy; -int grpc_lb_round_robin_trace = 0; +grpc_tracer_flag grpc_lb_round_robin_trace = GRPC_TRACER_INITIALIZER(false); /** List of entities waiting for a pick. * @@ -198,7 +198,7 @@ static void advance_last_picked_locked(round_robin_lb_policy *p) { GPR_ASSERT(p->ready_list_last_pick == &p->ready_list); } - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "[READYLIST, RR: %p] ADVANCED LAST PICK. NOW AT NODE %p (SC %p, " "CSC %p)", @@ -228,7 +228,7 @@ static ready_list *add_connected_sc_locked(round_robin_lb_policy *p, p->ready_list.prev->next = new_elem; p->ready_list.prev = new_elem; } - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "[READYLIST] ADDING NODE %p (Conn. SC %p)", (void *)new_elem, (void *)sd->subchannel); } @@ -256,7 +256,7 @@ static void remove_disconnected_sc_locked(round_robin_lb_policy *p, node->next->prev = node->prev; } - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "[READYLIST] REMOVED NODE %p (SC %p)", (void *)node, (void *)node->subchannel); } @@ -276,7 +276,7 @@ static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; ready_list *elem; - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "Destroying Round Robin policy at %p", (void *)pol); } @@ -312,7 +312,7 @@ static void rr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { pending_pick *pp; size_t i; - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "Shutting down Round Robin policy at %p", (void *)pol); } @@ -421,7 +421,7 @@ static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, pending_pick *pp; ready_list *selected; - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_INFO, "Round Robin %p trying to pick", (void *)pol); } @@ -434,7 +434,7 @@ static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, if (user_data != NULL) { *user_data = selected->user_data; } - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "[RR PICK] TARGET <-- CONNECTED SUBCHANNEL %p (NODE %p)", (void *)*target, (void *)selected); @@ -566,7 +566,7 @@ static void rr_connectivity_changed_locked(grpc_exec_ctx *exec_ctx, void *arg, if (pp->user_data != NULL) { *pp->user_data = selected->user_data; } - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "[RR CONN CHANGED] TARGET <-- SUBCHANNEL %p (NODE %p)", (void *)selected->subchannel, (void *)selected); @@ -724,7 +724,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, sc_args.args = new_args; grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( exec_ctx, args->client_channel_factory, &sc_args); - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { char *address_uri = grpc_sockaddr_to_uri(&addresses->addresses[i].address); gpr_log(GPR_DEBUG, "Created subchannel %p for address uri %s", @@ -768,7 +768,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, grpc_connectivity_state_init(&p->state_tracker, GRPC_CHANNEL_IDLE, "round_robin"); - if (grpc_lb_round_robin_trace) { + if (GRPC_TRACER_ON(grpc_lb_round_robin_trace)) { gpr_log(GPR_DEBUG, "Created RR policy at %p with %lu subchannels", (void *)p, (unsigned long)p->num_subchannels); } diff --git a/src/core/ext/filters/http/http_filters_plugin.c b/src/core/ext/filters/http/http_filters_plugin.c index 195a1a8119b6400d1d272eb47c54a6e6e014dda1..856a7dbd91e2078f67de1aeee5cbaa3b1a53b1e9 100644 --- a/src/core/ext/filters/http/http_filters_plugin.c +++ b/src/core/ext/filters/http/http_filters_plugin.c @@ -37,6 +37,7 @@ #include "src/core/ext/filters/http/message_compress/message_compress_filter.h" #include "src/core/ext/filters/http/server/http_server_filter.h" #include "src/core/lib/channel/channel_stack_builder.h" +#include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/transport_impl.h" diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.c b/src/core/ext/filters/http/message_compress/message_compress_filter.c index 1da8cf69cbf39d7a2f6e8c983a34adc2ab125e27..5a54a6ed152d1c41dc05bb4be3d22a73f09f3fc3 100644 --- a/src/core/ext/filters/http/message_compress/message_compress_filter.c +++ b/src/core/ext/filters/http/message_compress/message_compress_filter.c @@ -47,6 +47,7 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" +#include "src/core/lib/surface/call.h" #include "src/core/lib/transport/static_metadata.h" #define INITIAL_METADATA_UNSEEN 0 @@ -197,7 +198,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx, did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm, &calld->slices, &tmp); if (did_compress) { - if (grpc_compression_trace) { + if (GRPC_TRACER_ON(grpc_compression_trace)) { char *algo_name; const size_t before_size = calld->slices.length; const size_t after_size = tmp.length; @@ -211,7 +212,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx, grpc_slice_buffer_swap(&calld->slices, &tmp); calld->send_flags |= GRPC_WRITE_INTERNAL_COMPRESS; } else { - if (grpc_compression_trace) { + if (GRPC_TRACER_ON(grpc_compression_trace)) { char *algo_name; GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm, &algo_name)); diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.h b/src/core/ext/filters/http/message_compress/message_compress_filter.h index 75bfa17fba31b03aa9d3bc98e166cd01a6c7e2db..135da4da620badfd657fd08bd9ef18476f110574 100644 --- a/src/core/ext/filters/http/message_compress/message_compress_filter.h +++ b/src/core/ext/filters/http/message_compress/message_compress_filter.h @@ -38,8 +38,6 @@ #include "src/core/lib/channel/channel_stack.h" -extern int grpc_compression_trace; - /** Compression filter for outgoing data. * * See <grpc/compression.h> for the available compression settings. diff --git a/src/core/ext/filters/http/server/http_server_filter.c b/src/core/ext/filters/http/server/http_server_filter.c index ff857878e46b527122382181b42659d842d47159..9e495f4d42288df8b9993d7e147818666fa18a02 100644 --- a/src/core/ext/filters/http/server/http_server_filter.c +++ b/src/core/ext/filters/http/server/http_server_filter.c @@ -46,8 +46,6 @@ #define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1 -extern int grpc_http_trace; - typedef struct call_data { grpc_linked_mdelem status; grpc_linked_mdelem content_type; diff --git a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c index 41a91204b20a53780aa0f815f0e19849e41dd877..7fb75e3a4f0c0284951718adffd728b63da007d6 100644 --- a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +++ b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c @@ -54,9 +54,6 @@ typedef struct call_data { bool workaround_active; } call_data; -typedef struct channel_data { -} channel_data; - // Find the user agent metadata element in the batch static bool get_user_agent_mdelem(const grpc_metadata_batch* batch, grpc_mdelem* md) { @@ -192,7 +189,7 @@ const grpc_channel_filter grpc_workaround_cronet_compression_filter = { init_call_elem, grpc_call_stack_ignore_set_pollset_or_pollset_set, destroy_call_elem, - sizeof(channel_data), + 0, init_channel_elem, destroy_channel_elem, grpc_call_next_get_peer, @@ -208,15 +205,9 @@ static bool register_workaround_cronet_compression( if (a == NULL) { return true; } - if (a->type != GRPC_ARG_INTEGER) { - gpr_log(GPR_ERROR, "%s ignored: it must be an integer", - GRPC_ARG_WORKAROUND_CRONET_COMPRESSION); - return true; - } - if (a->value.integer == 0) { + if (grpc_channel_arg_get_bool(a, false) == false) { return true; } - grpc_enable_workaround(GRPC_WORKAROUND_ID_CRONET_COMPRESSION); return grpc_channel_stack_builder_prepend_filter( builder, &grpc_workaround_cronet_compression_filter, NULL, NULL); } diff --git a/src/core/ext/filters/workarounds/workaround_utils.c b/src/core/ext/filters/workarounds/workaround_utils.c index 8f90a3d1a9ab4a6655272d152a0ec87b51e88a01..1c565388e1003b593833890fe9c4159bacf696f9 100644 --- a/src/core/ext/filters/workarounds/workaround_utils.c +++ b/src/core/ext/filters/workarounds/workaround_utils.c @@ -34,12 +34,7 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> -typedef struct { - bool enabled; - user_agent_parser ua_parser; -} workaround_context; - -static workaround_context workarounds[GRPC_MAX_WORKAROUND_ID]; +user_agent_parser ua_parser[GRPC_MAX_WORKAROUND_ID]; static void destroy_user_agent_md(void *user_agent_md) { gpr_free(user_agent_md); @@ -55,8 +50,8 @@ grpc_workaround_user_agent_md *grpc_parse_user_agent(grpc_mdelem md) { } user_agent_md = gpr_malloc(sizeof(grpc_workaround_user_agent_md)); for (int i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) { - if (workarounds[i].enabled && workarounds[i].ua_parser) { - user_agent_md->workaround_active[i] = workarounds[i].ua_parser(md); + if (ua_parser[i]) { + user_agent_md->workaround_active[i] = ua_parser[i](md); } } grpc_mdelem_set_user_data(md, destroy_user_agent_md, (void *)user_agent_md); @@ -66,10 +61,5 @@ grpc_workaround_user_agent_md *grpc_parse_user_agent(grpc_mdelem md) { void grpc_register_workaround(uint32_t id, user_agent_parser parser) { GPR_ASSERT(id < GRPC_MAX_WORKAROUND_ID); - workarounds[id].ua_parser = parser; -} - -void grpc_enable_workaround(uint32_t id) { - GPR_ASSERT(id < GRPC_MAX_WORKAROUND_ID); - workarounds[id].enabled = true; + ua_parser[id] = parser; } diff --git a/src/core/ext/filters/workarounds/workaround_utils.h b/src/core/ext/filters/workarounds/workaround_utils.h index 19528ab16546609b55078a54f2561a4ff4a7f944..7cd70c12d89bb006936b7d17d9ad5d40534fca99 100644 --- a/src/core/ext/filters/workarounds/workaround_utils.h +++ b/src/core/ext/filters/workarounds/workaround_utils.h @@ -49,6 +49,4 @@ typedef bool (*user_agent_parser)(grpc_mdelem); void grpc_register_workaround(uint32_t id, user_agent_parser parser); -void grpc_enable_workaround(uint32_t id); - #endif diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c index 9c8505ddfa97e3b9de8f1515847d412cf9d42cf9..ad674b8eb47cc61e313eec24bcc732fff1b25e0c 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c @@ -101,7 +101,7 @@ grpc_channel *grpc_insecure_channel_create(const char *target, void *reserved) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( - "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3, + "grpc_insecure_channel_create(target=%s, args=%p, reserved=%p)", 3, (target, args, reserved)); GPR_ASSERT(reserved == NULL); // Add channel arg containing the client channel factory. diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index d6b79bd49233183e8d328aad4f99710e43c5f902..fb8ceaecb0649bd422313daeef30f31e6f2b35b2 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -89,8 +89,8 @@ static bool g_default_keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; #define MAX_CLIENT_STREAM_ID 0x7fffffffu -int grpc_http_trace = 0; -int grpc_flowctl_trace = 0; +grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false); +grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false); static const grpc_transport_vtable vtable; @@ -884,14 +884,23 @@ static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *gt, GPR_TIMER_BEGIN("write_action_begin_locked", 0); grpc_chttp2_transport *t = gt; GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE); - if (!t->closed && grpc_chttp2_begin_write(exec_ctx, t)) { - set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, - "begin writing"); - grpc_closure_sched(exec_ctx, &t->write_action, GRPC_ERROR_NONE); - } else { - set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE, - "begin writing nothing"); - GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing"); + switch (t->closed ? GRPC_CHTTP2_NOTHING_TO_WRITE + : grpc_chttp2_begin_write(exec_ctx, t)) { + case GRPC_CHTTP2_NOTHING_TO_WRITE: + set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE, + "begin writing nothing"); + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing"); + break; + case GRPC_CHTTP2_PARTIAL_WRITE: + set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE, + "begin writing partial"); + grpc_closure_sched(exec_ctx, &t->write_action, GRPC_ERROR_NONE); + break; + case GRPC_CHTTP2_FULL_WRITE: + set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, + "begin writing"); + grpc_closure_sched(exec_ctx, &t->write_action, GRPC_ERROR_NONE); + break; } GPR_TIMER_END("write_action_begin_locked", 0); } @@ -988,7 +997,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx, t->seen_goaway = 1; /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug - * data equal to “too_many_pings”, it should log the occurrence at a log level + * data equal to "too_many_pings", it should log the occurrence at a log level * that is enabled by default and double the configured KEEPALIVE_TIME used * for new connections on that channel. */ if (t->is_client && goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM && @@ -1095,7 +1104,7 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, return; } closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { const char *errstr = grpc_error_string(error); gpr_log(GPR_DEBUG, "complete_closure_step: %p refs=%d flags=0x%04x desc=%s err=%s", @@ -1240,7 +1249,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op, grpc_transport_stream_op_batch_payload *op_payload = op->payload; grpc_chttp2_transport *t = s->t; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { char *str = grpc_transport_stream_op_batch_string(op); gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str, op->on_complete); @@ -1483,9 +1492,9 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt; grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { char *str = grpc_transport_stream_op_batch_string(op); - gpr_log(GPR_DEBUG, "perform_stream_op[s=%p/%d]: %s", s, s->id, str); + gpr_log(GPR_DEBUG, "perform_stream_op[s=%p]: %s", s, str); gpr_free(str); } @@ -2130,27 +2139,29 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, double bdp_dbl) { - uint32_t bdp; - if (bdp_dbl <= 0) { - bdp = 0; - } else if (bdp_dbl > UINT32_MAX) { - bdp = UINT32_MAX; + int32_t bdp; + const int32_t kMinBDP = 128; + if (bdp_dbl <= kMinBDP) { + bdp = kMinBDP; + } else if (bdp_dbl > INT32_MAX) { + bdp = INT32_MAX; } else { - bdp = (uint32_t)(bdp_dbl); + bdp = (int32_t)(bdp_dbl); } int64_t delta = (int64_t)bdp - (int64_t)t->settings[GRPC_LOCAL_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]; - if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) { + if (delta == 0 || (delta > -bdp / 10 && delta < bdp / 10)) { return; } - if (grpc_bdp_estimator_trace) { + if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string, (int)bdp); } - push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp); - push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, bdp); + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, + (uint32_t)bdp); + push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE, (uint32_t)bdp); } static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, @@ -2305,7 +2316,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp, static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { grpc_chttp2_transport *t = tp; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string); } /* Reset the keepalive ping timer */ @@ -2318,7 +2329,7 @@ static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp, grpc_error *error) { grpc_chttp2_transport *t = tp; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string); } grpc_bdp_estimator_complete_ping(&t->bdp_estimator); @@ -2779,7 +2790,7 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_chttp2_stream_map_size(&t->stream_map) == 0) { /* Channel with no active streams: send a goaway to try and make it * disconnect cleanly */ - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory", t->peer_string); } @@ -2787,7 +2798,8 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"), GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM)); - } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) { + } else if (error == GRPC_ERROR_NONE && + GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR " streams", @@ -2808,7 +2820,7 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg, t->destructive_reclaimer_registered = false; if (error == GRPC_ERROR_NONE && n > 0) { grpc_chttp2_stream *s = grpc_chttp2_stream_map_rand(&t->stream_map); - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string, s->id); } diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h index c372174f2d52840a9ea80bcebdf6ac8c28726167..83b17d1936fcd57ec8dfc5c82c68b6fb6e0247b6 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.h +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.h @@ -34,11 +34,12 @@ #ifndef GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H #define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/transport/transport.h" -extern int grpc_http_trace; -extern int grpc_flowctl_trace; +extern grpc_tracer_flag grpc_http_trace; +extern grpc_tracer_flag grpc_flowctl_trace; grpc_transport *grpc_create_chttp2_transport( grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args, diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.c b/src/core/ext/transport/chttp2/transport/frame_settings.c index e3cd70d3f3bcbe7696361001df15e052f9a4f46a..dbaafb5929f0164065fa915f0a35cb428bdcbbe0 100644 --- a/src/core/ext/transport/chttp2/transport/frame_settings.c +++ b/src/core/ext/transport/chttp2/transport/frame_settings.c @@ -218,18 +218,18 @@ grpc_error *grpc_chttp2_settings_parser_parse(grpc_exec_ctx *exec_ctx, void *p, parser->incoming_settings[id] != parser->value) { t->initial_window_update += (int64_t)parser->value - parser->incoming_settings[id]; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "adding %d for initial_window change", (int)t->initial_window_update); } } parser->incoming_settings[id] = parser->value; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %s = %d", t->is_client ? "CLI" : "SVR", t->peer_string, sp->name, parser->value); } - } else if (grpc_http_trace) { + } else if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_ERROR, "CHTTP2: Ignoring unknown setting %d (value %d)", parser->id, parser->value); } diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c index 8fdd4ee77c1386dd83333400be782f7f171c3dc2..126e012aac9fc137ff6ee573e7fda8c51fef1b72 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c @@ -69,7 +69,7 @@ static grpc_slice_refcount terminal_slice_refcount = {NULL, NULL}; static const grpc_slice terminal_slice = {&terminal_slice_refcount, .data.refcounted = {0, 0}}; -extern int grpc_http_trace; +extern grpc_tracer_flag grpc_http_trace; typedef struct { int is_first_frame; @@ -425,7 +425,7 @@ static void hpack_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, "Reserved header (colon-prefixed) happening after regular ones."); } - if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(elem)) { + if (GRPC_TRACER_ON(grpc_http_trace) && !GRPC_MDELEM_IS_INTERNED(elem)) { char *k = grpc_slice_to_c_string(GRPC_MDKEY(elem)); char *v = grpc_slice_to_c_string(GRPC_MDVALUE(elem)); gpr_log( @@ -616,7 +616,7 @@ void grpc_chttp2_hpack_compressor_set_max_table_size( } } c->advertise_table_size_change = 1; - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size); } } diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.c b/src/core/ext/transport/chttp2/transport/hpack_parser.c index 1846a85fc65f37bc5de2fe31b0cc9f73c066e31f..bb98bc4a79fc5247616f5436dedd0bf2d6021725 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.c +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.c @@ -50,8 +50,6 @@ #include "src/core/lib/support/string.h" #include "src/core/lib/transport/http2_errors.h" -extern int grpc_http_trace; - typedef enum { NOT_BINARY, BINARY_BEGIN, @@ -666,7 +664,7 @@ static const uint8_t inverse_base64[256] = { /* emission helpers */ static grpc_error *on_hdr(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, grpc_mdelem md, int add_to_table) { - if (grpc_http_trace && !GRPC_MDELEM_IS_INTERNED(md)) { + if (GRPC_TRACER_ON(grpc_http_trace) && !GRPC_MDELEM_IS_INTERNED(md)) { char *k = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *v = grpc_slice_to_c_string(GRPC_MDVALUE(md)); gpr_log( @@ -1052,7 +1050,7 @@ static grpc_error *parse_lithdr_nvridx_v(grpc_exec_ctx *exec_ctx, static grpc_error *finish_max_tbl_size(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_parser *p, const uint8_t *cur, const uint8_t *end) { - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index); } grpc_error *err = diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.c b/src/core/ext/transport/chttp2/transport/hpack_table.c index 9dd41fdbe16caefdcf3a38c320bbbea5aeab7673..7aaff553396dafd141e4d36e8d7e0833feba4049 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_table.c +++ b/src/core/ext/transport/chttp2/transport/hpack_table.c @@ -40,9 +40,10 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/support/murmur_hash.h" -extern int grpc_http_trace; +extern grpc_tracer_flag grpc_http_trace; static struct { const char *key; @@ -260,7 +261,7 @@ void grpc_chttp2_hptbl_set_max_bytes(grpc_exec_ctx *exec_ctx, if (tbl->max_bytes == max_bytes) { return; } - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes); } while (tbl->mem_used > max_bytes) { @@ -284,7 +285,7 @@ grpc_error *grpc_chttp2_hptbl_set_current_table_size(grpc_exec_ctx *exec_ctx, gpr_free(msg); return err; } - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes); } while (tbl->mem_used > bytes) { diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 0aaa4aebe5f973f51d385573bad8c03a40568c4a..8d66e396ee85efb6020e37c70e019be3c9886236 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -552,9 +552,14 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, bool covered_by_poller, const char *reason); -/** Someone is unlocking the transport mutex: check to see if writes - are required, and frame them if so */ -bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); +typedef enum { + GRPC_CHTTP2_NOTHING_TO_WRITE, + GRPC_CHTTP2_PARTIAL_WRITE, + GRPC_CHTTP2_FULL_WRITE, +} grpc_chttp2_begin_write_result; + +grpc_chttp2_begin_write_result grpc_chttp2_begin_write( + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_error *error); @@ -629,13 +634,13 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx, #define GRPC_CHTTP2_CLIENT_CONNECT_STRLEN \ (sizeof(GRPC_CHTTP2_CLIENT_CONNECT_STRING) - 1) -extern int grpc_http_trace; -extern int grpc_flowctl_trace; +extern grpc_tracer_flag grpc_http_trace; +extern grpc_tracer_flag grpc_flowctl_trace; -#define GRPC_CHTTP2_IF_TRACING(stmt) \ - if (!(grpc_http_trace)) \ - ; \ - else \ +#define GRPC_CHTTP2_IF_TRACING(stmt) \ + if (!(GRPC_TRACER_ON(grpc_http_trace))) \ + ; \ + else \ stmt typedef enum { @@ -648,7 +653,7 @@ typedef enum { dst_var, src_context, src_var) \ do { \ assert(id1 == id2); \ - if (grpc_flowctl_trace) { \ + if (GRPC_TRACER_ON(grpc_flowctl_trace)) { \ grpc_chttp2_flowctl_trace( \ __FILE__, __LINE__, phase, GRPC_CHTTP2_FLOWCTL_MOVE, #dst_context, \ #dst_var, #src_context, #src_var, transport->is_client, id1, \ @@ -671,7 +676,7 @@ typedef enum { #define GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, transport, id, dst_context, \ dst_var, amount) \ do { \ - if (grpc_flowctl_trace) { \ + if (GRPC_TRACER_ON(grpc_flowctl_trace)) { \ grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase, \ GRPC_CHTTP2_FLOWCTL_CREDIT, #dst_context, \ #dst_var, NULL, #amount, transport->is_client, \ @@ -729,7 +734,7 @@ typedef enum { #define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \ dst_var, amount) \ do { \ - if (grpc_flowctl_trace) { \ + if (GRPC_TRACER_ON(grpc_flowctl_trace)) { \ grpc_chttp2_flowctl_trace(__FILE__, __LINE__, phase, \ GRPC_CHTTP2_FLOWCTL_DEBIT, #dst_context, \ #dst_var, NULL, #amount, transport->is_client, \ @@ -815,7 +820,7 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, /** Add a new ping strike to ping_recv_state.ping_strikes. If ping_recv_state.ping_strikes > ping_policy.max_ping_strikes, it sends GOAWAY with error code ENHANCE_YOUR_CALM and additional debug data resembling - “too_many_pings” followed by immediately closing the connection. */ + "too_many_pings" followed by immediately closing the connection. */ void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t); diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 638b137316fdd14773466d248a7aa06604f0b19d..1a676e2259659e23b6972988fcc8bb2bdd0136e4 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -324,7 +324,7 @@ static grpc_error *init_frame_parser(grpc_exec_ctx *exec_ctx, case GRPC_CHTTP2_FRAME_GOAWAY: return init_goaway_parser(exec_ctx, t); default: - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { gpr_log(GPR_ERROR, "Unknown frame type %02x", t->incoming_frame_type); } return init_skip_frame_parser(exec_ctx, t, 0); @@ -418,11 +418,9 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx, GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s, incoming_frame_size); - if ((int64_t)t->settings[GRPC_SENT_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] + - (int64_t)s->incoming_window_delta - (int64_t)s->announce_window <= - (int64_t)t->settings[GRPC_SENT_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] / + if ((int64_t)s->incoming_window_delta - (int64_t)s->announce_window <= + -(int64_t)t->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] / 2) { grpc_chttp2_become_writable(exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED, @@ -494,7 +492,7 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp, GPR_ASSERT(s != NULL); - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { char *key = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *value = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); @@ -574,7 +572,7 @@ static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp, GPR_ASSERT(s != NULL); - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { char *key = grpc_slice_to_c_string(GRPC_MDKEY(md)); char *value = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); @@ -807,7 +805,7 @@ static grpc_error *parse_frame_slice(grpc_exec_ctx *exec_ctx, if (err == GRPC_ERROR_NONE) { return err; } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) { - if (grpc_http_trace) { + if (GRPC_TRACER_ON(grpc_http_trace)) { const char *msg = grpc_error_string(err); gpr_log(GPR_ERROR, "%s", msg); } diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index 069780ae5af0bd0087b1c431ec692b114a13c0e8..5be1092946acd68ee88b06b4863cde9ee2a9701d 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -74,7 +74,8 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx, } if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) { /* ping already in-flight: wait */ - if (grpc_http_trace || grpc_bdp_estimator_trace) { + if (GRPC_TRACER_ON(grpc_http_trace) || + GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "Ping delayed [%p]: already pinging", t->peer_string); } return; @@ -82,7 +83,8 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx, if (t->ping_state.pings_before_data_required == 0 && t->ping_policy.max_pings_without_data != 0) { /* need to send something of substance before sending a ping again */ - if (grpc_http_trace || grpc_bdp_estimator_trace) { + if (GRPC_TRACER_ON(grpc_http_trace) || + GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d", t->peer_string, t->ping_state.pings_before_data_required, t->ping_policy.max_pings_without_data); @@ -96,7 +98,8 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx, (int)t->ping_policy.min_time_between_pings.tv_nsec);*/ if (gpr_time_cmp(elapsed, t->ping_policy.min_time_between_pings) < 0) { /* not enough elapsed time between successive pings */ - if (grpc_http_trace || grpc_bdp_estimator_trace) { + if (GRPC_TRACER_ON(grpc_http_trace) || + GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "Ping delayed [%p]: not enough time elapsed since last ping", t->peer_string); @@ -160,19 +163,22 @@ static bool stream_ref_if_not_destroyed(gpr_refcount *r) { return true; } +/* How many bytes of incoming flow control would we like to advertise */ uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) { - return (uint32_t)GPR_MAX( + return (uint32_t)GPR_MIN( (int64_t)((1u << 31) - 1), t->stream_total_over_incoming_window + - (int64_t)GPR_MAX( - t->settings[GRPC_SENT_SETTINGS] - [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] - - t->stream_total_under_incoming_window, - 0)); + t->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); } -bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, - grpc_chttp2_transport *t) { +/* How many bytes would we like to put on the wire during a single syscall */ +static uint32_t target_write_size(grpc_chttp2_transport *t) { + return 1024 * 1024; +} + +grpc_chttp2_begin_write_result grpc_chttp2_begin_write( + grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_chttp2_stream *s; GPR_TIMER_BEGIN("grpc_chttp2_begin_write", 0); @@ -206,9 +212,20 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, } } + bool partial_write = false; + /* for each grpc_chttp2_stream that's become writable, frame it's data (according to available window sizes) and add to the output buffer */ - while (grpc_chttp2_list_pop_writable_stream(t, &s)) { + while (true) { + if (t->outbuf.length > target_write_size(t)) { + partial_write = true; + break; + } + + if (!grpc_chttp2_list_pop_writable_stream(t, &s)) { + break; + } + bool sent_initial_metadata = s->sent_initial_metadata; bool now_writing = false; @@ -395,7 +412,9 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, GPR_TIMER_END("grpc_chttp2_begin_write", 0); - return t->outbuf.count > 0; + return t->outbuf.count > 0 ? (partial_write ? GRPC_CHTTP2_PARTIAL_WRITE + : GRPC_CHTTP2_FULL_WRITE) + : GRPC_CHTTP2_NOTHING_TO_WRITE; } void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, diff --git a/src/core/lib/channel/channel_stack.c b/src/core/lib/channel/channel_stack.c index 94382980eb3949c4a7942ad4946965ed978a9448..7db54d11074a608e9b20a8d33e09f72434603916 100644 --- a/src/core/lib/channel/channel_stack.c +++ b/src/core/lib/channel/channel_stack.c @@ -38,7 +38,7 @@ #include <stdlib.h> #include <string.h> -int grpc_trace_channel = 0; +grpc_tracer_flag grpc_trace_channel = GRPC_TRACER_INITIALIZER(false); /* Memory layouts. diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index fdbcbdb01850678dea891625d3e752f6de19992e..c26d61b2ef4d1aa20a5a43d3fb9d61d0aeed22dd 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -307,10 +307,10 @@ void grpc_call_element_signal_error(grpc_exec_ctx *exec_ctx, grpc_call_element *cur_elem, grpc_error *error); -extern int grpc_trace_channel; +extern grpc_tracer_flag grpc_trace_channel; #define GRPC_CALL_LOG_OP(sev, elem, op) \ - if (grpc_trace_channel) grpc_call_log_op(sev, elem, op) + if (GRPC_TRACER_ON(grpc_trace_channel)) grpc_call_log_op(sev, elem, op) #ifdef __cplusplus } diff --git a/src/core/lib/channel/channel_stack_builder.c b/src/core/lib/channel/channel_stack_builder.c index 88c02edb70e423499899a93ac9a1172b6bae06c5..44b030e4d1f0757afb54d14d3a9522d3759c920f 100644 --- a/src/core/lib/channel/channel_stack_builder.c +++ b/src/core/lib/channel/channel_stack_builder.c @@ -38,7 +38,8 @@ #include <grpc/support/alloc.h> #include <grpc/support/string_util.h> -int grpc_trace_channel_stack_builder = 0; +grpc_tracer_flag grpc_trace_channel_stack_builder = + GRPC_TRACER_INITIALIZER(false); typedef struct filter_node { struct filter_node *next; diff --git a/src/core/lib/channel/channel_stack_builder.h b/src/core/lib/channel/channel_stack_builder.h index c78111b00d01e744e659b4b7078c0a27dc5aae6f..8cb36eb117e320dd132ade25d4a001c29aba5ecf 100644 --- a/src/core/lib/channel/channel_stack_builder.h +++ b/src/core/lib/channel/channel_stack_builder.h @@ -165,7 +165,7 @@ grpc_error *grpc_channel_stack_builder_finish( void grpc_channel_stack_builder_destroy(grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder); -extern int grpc_trace_channel_stack_builder; +extern grpc_tracer_flag grpc_trace_channel_stack_builder; #ifdef __cplusplus } diff --git a/src/core/lib/debug/trace.c b/src/core/lib/debug/trace.c index c56046785b380571d60e2b599318be96673360b6..4dfea44c57eabd65147fc5c5e23c52ed893933b4 100644 --- a/src/core/lib/debug/trace.c +++ b/src/core/lib/debug/trace.c @@ -35,24 +35,31 @@ #include <string.h> -#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include "src/core/lib/support/env.h" +int grpc_tracer_set_enabled(const char *name, int enabled); + typedef struct tracer { const char *name; - int *flag; + grpc_tracer_flag *flag; struct tracer *next; } tracer; static tracer *tracers; -void grpc_register_tracer(const char *name, int *flag) { +#ifdef GRPC_THREADSAFE_TRACER +#define TRACER_SET(flag, on) gpr_atm_no_barrier_store(&(flag).value, (on)) +#else +#define TRACER_SET(flag, on) (flag).value = (on) +#endif + +void grpc_register_tracer(const char *name, grpc_tracer_flag *flag) { tracer *t = gpr_malloc(sizeof(*t)); t->name = name; t->flag = flag; t->next = tracers; - *flag = 0; + TRACER_SET(*flag, false); tracers = t; } @@ -121,13 +128,13 @@ int grpc_tracer_set_enabled(const char *name, int enabled) { tracer *t; if (0 == strcmp(name, "all")) { for (t = tracers; t; t = t->next) { - *t->flag = enabled; + TRACER_SET(*t->flag, enabled); } } else { int found = 0; for (t = tracers; t; t = t->next) { if (0 == strcmp(name, t->name)) { - *t->flag = enabled; + TRACER_SET(*t->flag, enabled); found = 1; } } diff --git a/src/core/lib/debug/trace.h b/src/core/lib/debug/trace.h index 7afc38db7e1f936f7fffb20564cd6ed4daeea57e..ba432574d06e3de73834a4544df747b257b4f5e4 100644 --- a/src/core/lib/debug/trace.h +++ b/src/core/lib/debug/trace.h @@ -34,9 +34,35 @@ #ifndef GRPC_CORE_LIB_DEBUG_TRACE_H #define GRPC_CORE_LIB_DEBUG_TRACE_H +#include <grpc/support/atm.h> #include <grpc/support/port_platform.h> +#include <stdbool.h> -void grpc_register_tracer(const char *name, int *flag); +#if defined(__has_feature) +#if __has_feature(thread_sanitizer) +#define GRPC_THREADSAFE_TRACER +#endif +#endif + +typedef struct { +#ifdef GRPC_THREADSAFE_TRACER + gpr_atm value; +#else + bool value; +#endif +} grpc_tracer_flag; + +#ifdef GRPC_THREADSAFE_TRACER +#define GRPC_TRACER_ON(flag) (gpr_atm_no_barrier_load(&(flag).value) != 0) +#define GRPC_TRACER_INITIALIZER(on) \ + { (gpr_atm)(on) } +#else +#define GRPC_TRACER_ON(flag) ((flag).value) +#define GRPC_TRACER_INITIALIZER(on) \ + { (on) } +#endif + +void grpc_register_tracer(const char *name, grpc_tracer_flag *flag); void grpc_tracer_init(const char *env_var_name); void grpc_tracer_shutdown(void); diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c index aac506b800da3fe12e99ee1859ae6aa4bfa14149..a4357978e4334bf9f918ee206185501e6320b665 100644 --- a/src/core/lib/http/parser.c +++ b/src/core/lib/http/parser.c @@ -40,7 +40,7 @@ #include <grpc/support/log.h> #include <grpc/support/useful.h> -int grpc_http1_trace = 0; +grpc_tracer_flag grpc_http1_trace = GRPC_TRACER_INITIALIZER(false); static char *buf2str(void *buffer, size_t length) { char *out = gpr_malloc(length + 1); @@ -308,7 +308,7 @@ static grpc_error *addbyte(grpc_http_parser *parser, uint8_t byte, case GRPC_HTTP_FIRST_LINE: case GRPC_HTTP_HEADERS: if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) { - if (grpc_http1_trace) + if (GRPC_TRACER_ON(grpc_http1_trace)) gpr_log(GPR_ERROR, "HTTP header max line length (%d) exceeded", GRPC_HTTP_PARSER_MAX_HEADER_LENGTH); return GRPC_ERROR_CREATE_FROM_STATIC_STRING( diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h index a68011dd4394a1cbc2500ad347e84f4a0c26c39e..a155fecf118de807a6fba5386e0144ed90dc8436 100644 --- a/src/core/lib/http/parser.h +++ b/src/core/lib/http/parser.h @@ -36,6 +36,7 @@ #include <grpc/slice.h> #include <grpc/support/port_platform.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/error.h" /* Maximum length of a header string of the form 'Key: Value\r\n' */ @@ -121,6 +122,6 @@ grpc_error *grpc_http_parser_eof(grpc_http_parser *parser); void grpc_http_request_destroy(grpc_http_request *request); void grpc_http_response_destroy(grpc_http_response *response); -extern int grpc_http1_trace; +extern grpc_tracer_flag grpc_http1_trace; #endif /* GRPC_CORE_LIB_HTTP_PARSER_H */ diff --git a/src/core/lib/iomgr/combiner.c b/src/core/lib/iomgr/combiner.c index 05cdbdad2b78e2bcc5ae9d4e3eab66dbae12767b..863f22c6141b7fc205cd45ffcb23af1cf3c2d124 100644 --- a/src/core/lib/iomgr/combiner.c +++ b/src/core/lib/iomgr/combiner.c @@ -42,13 +42,13 @@ #include "src/core/lib/iomgr/workqueue.h" #include "src/core/lib/profiling/timers.h" -int grpc_combiner_trace = 0; +grpc_tracer_flag grpc_combiner_trace = GRPC_TRACER_INITIALIZER(false); -#define GRPC_COMBINER_TRACE(fn) \ - do { \ - if (grpc_combiner_trace) { \ - fn; \ - } \ +#define GRPC_COMBINER_TRACE(fn) \ + do { \ + if (GRPC_TRACER_ON(grpc_combiner_trace)) { \ + fn; \ + } \ } while (0) #define STATE_UNORPHANED 1 diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 75dcb0b70a4268e97c4c20b77dc3f28826d4539d..6ab7a2b26b2a611551d7a2ffc2943127ea9dd3e8 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -37,6 +37,7 @@ #include <stddef.h> #include <grpc/support/atm.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/support/mpscq.h" @@ -78,6 +79,6 @@ grpc_closure_scheduler *grpc_combiner_finally_scheduler(grpc_combiner *lock, bool grpc_combiner_continue_exec_ctx(grpc_exec_ctx *exec_ctx); -extern int grpc_combiner_trace; +extern grpc_tracer_flag grpc_combiner_trace; #endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ diff --git a/src/core/lib/iomgr/ev_epoll1_linux.c b/src/core/lib/iomgr/ev_epoll1_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..ad69f808cdb7bd44120e05d857ff7b5dedad4bc7 --- /dev/null +++ b/src/core/lib/iomgr/ev_epoll1_linux.c @@ -0,0 +1,984 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +/* This polling engine is only relevant on linux kernels supporting epoll() */ +#ifdef GRPC_LINUX_EPOLL + +#include "src/core/lib/iomgr/ev_epoll1_linux.h" + +#include <assert.h> +#include <errno.h> +#include <poll.h> +#include <pthread.h> +#include <string.h> +#include <sys/epoll.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/cpu.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/tls.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/lockfree_event.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/iomgr/workqueue.h" +#include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/block_annotate.h" + +static grpc_wakeup_fd global_wakeup_fd; +static int g_epfd; + +/******************************************************************************* + * Fd Declarations + */ + +struct grpc_fd { + int fd; + + gpr_atm read_closure; + gpr_atm write_closure; + + struct grpc_fd *freelist_next; + + /* The pollset that last noticed that the fd is readable. The actual type + * stored in this is (grpc_pollset *) */ + gpr_atm read_notifier_pollset; + + grpc_iomgr_object iomgr_object; +}; + +static void fd_global_init(void); +static void fd_global_shutdown(void); + +/******************************************************************************* + * Pollset Declarations + */ + +typedef enum { UNKICKED, KICKED, DESIGNATED_POLLER } kick_state; + +struct grpc_pollset_worker { + kick_state kick_state; + bool initialized_cv; + grpc_pollset_worker *next; + grpc_pollset_worker *prev; + gpr_cv cv; + grpc_closure_list schedule_on_end_work; +}; + +#define MAX_NEIGHBOURHOODS 1024 + +typedef struct pollset_neighbourhood { + gpr_mu mu; + grpc_pollset *active_root; + char pad[GPR_CACHELINE_SIZE]; +} pollset_neighbourhood; + +struct grpc_pollset { + gpr_mu mu; + pollset_neighbourhood *neighbourhood; + bool reassigning_neighbourhood; + grpc_pollset_worker *root_worker; + bool kicked_without_poller; + bool seen_inactive; + bool shutting_down; /* Is the pollset shutting down ? */ + bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ + grpc_closure *shutdown_closure; /* Called after after shutdown is complete */ + int begin_refs; + + grpc_pollset *next; + grpc_pollset *prev; +}; + +/******************************************************************************* + * Pollset-set Declarations + */ + +struct grpc_pollset_set {}; + +/******************************************************************************* + * Common helpers + */ + +static bool append_error(grpc_error **composite, grpc_error *error, + const char *desc) { + if (error == GRPC_ERROR_NONE) return true; + if (*composite == GRPC_ERROR_NONE) { + *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); + } + *composite = grpc_error_add_child(*composite, error); + return false; +} + +/******************************************************************************* + * Fd Definitions + */ + +/* We need to keep a freelist not because of any concerns of malloc performance + * but instead so that implementations with multiple threads in (for example) + * epoll_wait deal with the race between pollset removal and incoming poll + * notifications. + * + * The problem is that the poller ultimately holds a reference to this + * object, so it is very difficult to know when is safe to free it, at least + * without some expensive synchronization. + * + * If we keep the object freelisted, in the worst case losing this race just + * becomes a spurious read notification on a reused fd. + */ + +/* The alarm system needs to be able to wakeup 'some poller' sometimes + * (specifically when a new alarm needs to be triggered earlier than the next + * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a + * case occurs. */ + +static grpc_fd *fd_freelist = NULL; +static gpr_mu fd_freelist_mu; + +static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } + +static void fd_global_shutdown(void) { + gpr_mu_lock(&fd_freelist_mu); + gpr_mu_unlock(&fd_freelist_mu); + while (fd_freelist != NULL) { + grpc_fd *fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + gpr_free(fd); + } + gpr_mu_destroy(&fd_freelist_mu); +} + +static grpc_fd *fd_create(int fd, const char *name) { + grpc_fd *new_fd = NULL; + + gpr_mu_lock(&fd_freelist_mu); + if (fd_freelist != NULL) { + new_fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + } + gpr_mu_unlock(&fd_freelist_mu); + + if (new_fd == NULL) { + new_fd = gpr_malloc(sizeof(grpc_fd)); + } + + new_fd->fd = fd; + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); + gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); + + new_fd->freelist_next = NULL; + + char *fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); +#ifdef GRPC_FD_REF_COUNT_DEBUG + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); +#endif + gpr_free(fd_name); + + struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET), + .data.ptr = new_fd}; + if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, fd, &ev) != 0) { + gpr_log(GPR_ERROR, "epoll_ctl failed: %s", strerror(errno)); + } + + return new_fd; +} + +static int fd_wrapped_fd(grpc_fd *fd) { return fd->fd; } + +/* Might be called multiple times */ +static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { + shutdown(fd->fd, SHUT_RDWR); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + } + GRPC_ERROR_UNREF(why); +} + +static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *on_done, int *release_fd, + const char *reason) { + grpc_error *error = GRPC_ERROR_NONE; + + if (!grpc_lfev_is_shutdown(&fd->read_closure)) { + fd_shutdown(exec_ctx, fd, GRPC_ERROR_CREATE_FROM_COPIED_STRING(reason)); + } + + /* If release_fd is not NULL, we should be relinquishing control of the file + descriptor fd->fd (but we still own the grpc_fd structure). */ + if (release_fd != NULL) { + *release_fd = fd->fd; + } else { + close(fd->fd); + } + + grpc_closure_sched(exec_ctx, on_done, GRPC_ERROR_REF(error)); + + grpc_iomgr_unregister_object(&fd->iomgr_object); + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); + + gpr_mu_lock(&fd_freelist_mu); + fd->freelist_next = fd_freelist; + fd_freelist = fd; + gpr_mu_unlock(&fd_freelist_mu); +} + +static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, + grpc_fd *fd) { + gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); + return (grpc_pollset *)notifier; +} + +static bool fd_is_shutdown(grpc_fd *fd) { + return grpc_lfev_is_shutdown(&fd->read_closure); +} + +static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure); +} + +static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure); +} + +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { + return (grpc_workqueue *)0xb0b51ed; +} + +static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_pollset *notifier) { + grpc_lfev_set_ready(exec_ctx, &fd->read_closure); + + /* Note, it is possible that fd_become_readable might be called twice with + different 'notifier's when an fd becomes readable and it is in two epoll + sets (This can happen briefly during polling island merges). In such cases + it does not really matter which notifer is set as the read_notifier_pollset + (They would both point to the same polling island anyway) */ + /* Use release store to match with acquire load in fd_get_read_notifier */ + gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); +} + +static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { + grpc_lfev_set_ready(exec_ctx, &fd->write_closure); +} + +/******************************************************************************* + * Pollset Definitions + */ + +GPR_TLS_DECL(g_current_thread_pollset); +GPR_TLS_DECL(g_current_thread_worker); +static gpr_atm g_active_poller; +static pollset_neighbourhood *g_neighbourhoods; +static size_t g_num_neighbourhoods; +static gpr_mu g_wq_mu; +static grpc_closure_list g_wq_items; + +/* Return true if first in list */ +static bool worker_insert(grpc_pollset *pollset, grpc_pollset_worker *worker) { + if (pollset->root_worker == NULL) { + pollset->root_worker = worker; + worker->next = worker->prev = worker; + return true; + } else { + worker->next = pollset->root_worker; + worker->prev = worker->next->prev; + worker->next->prev = worker; + worker->prev->next = worker; + return false; + } +} + +/* Return true if last in list */ +typedef enum { EMPTIED, NEW_ROOT, REMOVED } worker_remove_result; + +static worker_remove_result worker_remove(grpc_pollset *pollset, + grpc_pollset_worker *worker) { + if (worker == pollset->root_worker) { + if (worker == worker->next) { + pollset->root_worker = NULL; + return EMPTIED; + } else { + pollset->root_worker = worker->next; + worker->prev->next = worker->next; + worker->next->prev = worker->prev; + return NEW_ROOT; + } + } else { + worker->prev->next = worker->next; + worker->next->prev = worker->prev; + return REMOVED; + } +} + +static size_t choose_neighbourhood(void) { + return (size_t)gpr_cpu_current_cpu() % g_num_neighbourhoods; +} + +static grpc_error *pollset_global_init(void) { + gpr_tls_init(&g_current_thread_pollset); + gpr_tls_init(&g_current_thread_worker); + gpr_atm_no_barrier_store(&g_active_poller, 0); + global_wakeup_fd.read_fd = -1; + grpc_error *err = grpc_wakeup_fd_init(&global_wakeup_fd); + gpr_mu_init(&g_wq_mu); + g_wq_items = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT; + if (err != GRPC_ERROR_NONE) return err; + struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLET), + .data.ptr = &global_wakeup_fd}; + if (epoll_ctl(g_epfd, EPOLL_CTL_ADD, global_wakeup_fd.read_fd, &ev) != 0) { + return GRPC_OS_ERROR(errno, "epoll_ctl"); + } + g_num_neighbourhoods = GPR_CLAMP(gpr_cpu_num_cores(), 1, MAX_NEIGHBOURHOODS); + g_neighbourhoods = + gpr_zalloc(sizeof(*g_neighbourhoods) * g_num_neighbourhoods); + for (size_t i = 0; i < g_num_neighbourhoods; i++) { + gpr_mu_init(&g_neighbourhoods[i].mu); + } + return GRPC_ERROR_NONE; +} + +static void pollset_global_shutdown(void) { + gpr_tls_destroy(&g_current_thread_pollset); + gpr_tls_destroy(&g_current_thread_worker); + gpr_mu_destroy(&g_wq_mu); + if (global_wakeup_fd.read_fd != -1) grpc_wakeup_fd_destroy(&global_wakeup_fd); + for (size_t i = 0; i < g_num_neighbourhoods; i++) { + gpr_mu_destroy(&g_neighbourhoods[i].mu); + } + gpr_free(g_neighbourhoods); +} + +static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { + gpr_mu_init(&pollset->mu); + *mu = &pollset->mu; + pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()]; + pollset->seen_inactive = true; +} + +static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { + gpr_mu_lock(&pollset->mu); + if (!pollset->seen_inactive) { + pollset_neighbourhood *neighbourhood = pollset->neighbourhood; + gpr_mu_unlock(&pollset->mu); + retry_lock_neighbourhood: + gpr_mu_lock(&neighbourhood->mu); + gpr_mu_lock(&pollset->mu); + if (!pollset->seen_inactive) { + if (pollset->neighbourhood != neighbourhood) { + gpr_mu_unlock(&neighbourhood->mu); + neighbourhood = pollset->neighbourhood; + gpr_mu_unlock(&pollset->mu); + goto retry_lock_neighbourhood; + } + pollset->prev->next = pollset->next; + pollset->next->prev = pollset->prev; + if (pollset == pollset->neighbourhood->active_root) { + pollset->neighbourhood->active_root = + pollset->next == pollset ? NULL : pollset->next; + } + } + gpr_mu_unlock(&pollset->neighbourhood->mu); + } + gpr_mu_unlock(&pollset->mu); + gpr_mu_destroy(&pollset->mu); +} + +static grpc_error *pollset_kick_all(grpc_pollset *pollset) { + grpc_error *error = GRPC_ERROR_NONE; + if (pollset->root_worker != NULL) { + grpc_pollset_worker *worker = pollset->root_worker; + do { + if (worker->initialized_cv) { + worker->kick_state = KICKED; + gpr_cv_signal(&worker->cv); + } else { + worker->kick_state = KICKED; + append_error(&error, grpc_wakeup_fd_wakeup(&global_wakeup_fd), + "pollset_shutdown"); + } + + worker = worker->next; + } while (worker != pollset->root_worker); + } + return error; +} + +static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset) { + if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL && + pollset->begin_refs == 0) { + grpc_closure_sched(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE); + pollset->shutdown_closure = NULL; + } +} + +static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_closure *closure) { + GPR_ASSERT(pollset->shutdown_closure == NULL); + pollset->shutdown_closure = closure; + GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset)); + pollset_maybe_finish_shutdown(exec_ctx, pollset); +} + +#define MAX_EPOLL_EVENTS 100 + +static int poll_deadline_to_millis_timeout(gpr_timespec deadline, + gpr_timespec now) { + gpr_timespec timeout; + if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { + return -1; + } + + if (gpr_time_cmp(deadline, now) <= 0) { + return 0; + } + + static const gpr_timespec round_up = { + .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1}; + timeout = gpr_time_sub(deadline, now); + int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up)); + return millis >= 1 ? millis : 1; +} + +static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + gpr_timespec now, gpr_timespec deadline) { + struct epoll_event events[MAX_EPOLL_EVENTS]; + static const char *err_desc = "pollset_poll"; + + int timeout = poll_deadline_to_millis_timeout(deadline, now); + + if (timeout != 0) { + GRPC_SCHEDULING_START_BLOCKING_REGION; + } + int r; + do { + r = epoll_wait(g_epfd, events, MAX_EPOLL_EVENTS, timeout); + } while (r < 0 && errno == EINTR); + if (timeout != 0) { + GRPC_SCHEDULING_END_BLOCKING_REGION; + } + + if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait"); + + grpc_error *error = GRPC_ERROR_NONE; + for (int i = 0; i < r; i++) { + void *data_ptr = events[i].data.ptr; + if (data_ptr == &global_wakeup_fd) { + gpr_mu_lock(&g_wq_mu); + grpc_closure_list_move(&g_wq_items, &exec_ctx->closure_list); + gpr_mu_unlock(&g_wq_mu); + append_error(&error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd), + err_desc); + } else { + grpc_fd *fd = (grpc_fd *)(data_ptr); + bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0; + bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0; + bool write_ev = (events[i].events & EPOLLOUT) != 0; + if (read_ev || cancel) { + fd_become_readable(exec_ctx, fd, pollset); + } + if (write_ev || cancel) { + fd_become_writable(exec_ctx, fd); + } + } + } + + return error; +} + +static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker, + grpc_pollset_worker **worker_hdl, gpr_timespec *now, + gpr_timespec deadline) { + if (worker_hdl != NULL) *worker_hdl = worker; + worker->initialized_cv = false; + worker->kick_state = UNKICKED; + worker->schedule_on_end_work = (grpc_closure_list)GRPC_CLOSURE_LIST_INIT; + pollset->begin_refs++; + + if (pollset->seen_inactive) { + // pollset has been observed to be inactive, we need to move back to the + // active list + bool is_reassigning = false; + if (!pollset->reassigning_neighbourhood) { + is_reassigning = true; + pollset->reassigning_neighbourhood = true; + pollset->neighbourhood = &g_neighbourhoods[choose_neighbourhood()]; + } + pollset_neighbourhood *neighbourhood = pollset->neighbourhood; + gpr_mu_unlock(&pollset->mu); + // pollset unlocked: state may change (even worker->kick_state) + retry_lock_neighbourhood: + gpr_mu_lock(&neighbourhood->mu); + gpr_mu_lock(&pollset->mu); + if (pollset->seen_inactive) { + if (neighbourhood != pollset->neighbourhood) { + gpr_mu_unlock(&neighbourhood->mu); + neighbourhood = pollset->neighbourhood; + gpr_mu_unlock(&pollset->mu); + goto retry_lock_neighbourhood; + } + pollset->seen_inactive = false; + if (neighbourhood->active_root == NULL) { + neighbourhood->active_root = pollset->next = pollset->prev = pollset; + if (gpr_atm_no_barrier_cas(&g_active_poller, 0, (gpr_atm)worker)) { + worker->kick_state = DESIGNATED_POLLER; + } + } else { + pollset->next = neighbourhood->active_root; + pollset->prev = pollset->next->prev; + pollset->next->prev = pollset->prev->next = pollset; + } + } + if (is_reassigning) { + GPR_ASSERT(pollset->reassigning_neighbourhood); + pollset->reassigning_neighbourhood = false; + } + gpr_mu_unlock(&neighbourhood->mu); + } + worker_insert(pollset, worker); + pollset->begin_refs--; + if (worker->kick_state == UNKICKED) { + GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker); + worker->initialized_cv = true; + gpr_cv_init(&worker->cv); + while (worker->kick_state == UNKICKED && + pollset->shutdown_closure == NULL) { + if (gpr_cv_wait(&worker->cv, &pollset->mu, deadline) && + worker->kick_state == UNKICKED) { + worker->kick_state = KICKED; + } + } + *now = gpr_now(now->clock_type); + } + + return worker->kick_state == DESIGNATED_POLLER && + pollset->shutdown_closure == NULL; +} + +static bool check_neighbourhood_for_available_poller( + pollset_neighbourhood *neighbourhood) { + bool found_worker = false; + do { + grpc_pollset *inspect = neighbourhood->active_root; + if (inspect == NULL) { + break; + } + gpr_mu_lock(&inspect->mu); + GPR_ASSERT(!inspect->seen_inactive); + grpc_pollset_worker *inspect_worker = inspect->root_worker; + if (inspect_worker != NULL) { + do { + switch (inspect_worker->kick_state) { + case UNKICKED: + if (gpr_atm_no_barrier_cas(&g_active_poller, 0, + (gpr_atm)inspect_worker)) { + inspect_worker->kick_state = DESIGNATED_POLLER; + if (inspect_worker->initialized_cv) { + gpr_cv_signal(&inspect_worker->cv); + } + } + // even if we didn't win the cas, there's a worker, we can stop + found_worker = true; + break; + case KICKED: + break; + case DESIGNATED_POLLER: + found_worker = true; // ok, so someone else found the worker, but + // we'll accept that + break; + } + inspect_worker = inspect_worker->next; + } while (inspect_worker != inspect->root_worker); + } + if (!found_worker) { + inspect->seen_inactive = true; + if (inspect == neighbourhood->active_root) { + neighbourhood->active_root = + inspect->next == inspect ? NULL : inspect->next; + } + inspect->next->prev = inspect->prev; + inspect->prev->next = inspect->next; + inspect->next = inspect->prev = NULL; + } + gpr_mu_unlock(&inspect->mu); + } while (!found_worker); + return found_worker; +} + +static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_pollset_worker *worker, + grpc_pollset_worker **worker_hdl) { + if (worker_hdl != NULL) *worker_hdl = NULL; + worker->kick_state = KICKED; + grpc_closure_list_move(&worker->schedule_on_end_work, + &exec_ctx->closure_list); + if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) { + if (worker->next != worker && worker->next->kick_state == UNKICKED) { + GPR_ASSERT(worker->next->initialized_cv); + gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next); + worker->next->kick_state = DESIGNATED_POLLER; + gpr_cv_signal(&worker->next->cv); + if (grpc_exec_ctx_has_work(exec_ctx)) { + gpr_mu_unlock(&pollset->mu); + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(&pollset->mu); + } + } else { + gpr_atm_no_barrier_store(&g_active_poller, 0); + gpr_mu_unlock(&pollset->mu); + size_t poller_neighbourhood_idx = + (size_t)(pollset->neighbourhood - g_neighbourhoods); + bool found_worker = false; + bool scan_state[MAX_NEIGHBOURHOODS]; + for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) { + pollset_neighbourhood *neighbourhood = + &g_neighbourhoods[(poller_neighbourhood_idx + i) % + g_num_neighbourhoods]; + if (gpr_mu_trylock(&neighbourhood->mu)) { + found_worker = + check_neighbourhood_for_available_poller(neighbourhood); + gpr_mu_unlock(&neighbourhood->mu); + scan_state[i] = true; + } else { + scan_state[i] = false; + } + } + for (size_t i = 0; !found_worker && i < g_num_neighbourhoods; i++) { + if (scan_state[i]) continue; + pollset_neighbourhood *neighbourhood = + &g_neighbourhoods[(poller_neighbourhood_idx + i) % + g_num_neighbourhoods]; + gpr_mu_lock(&neighbourhood->mu); + found_worker = check_neighbourhood_for_available_poller(neighbourhood); + gpr_mu_unlock(&neighbourhood->mu); + } + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(&pollset->mu); + } + } else if (grpc_exec_ctx_has_work(exec_ctx)) { + gpr_mu_unlock(&pollset->mu); + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(&pollset->mu); + } + if (worker->initialized_cv) { + gpr_cv_destroy(&worker->cv); + } + if (EMPTIED == worker_remove(pollset, worker)) { + pollset_maybe_finish_shutdown(exec_ctx, pollset); + } + GPR_ASSERT(gpr_atm_no_barrier_load(&g_active_poller) != (gpr_atm)worker); +} + +/* pollset->po.mu lock must be held by the caller before calling this. + The function pollset_work() may temporarily release the lock (pollset->po.mu) + during the course of its execution but it will always re-acquire the lock and + ensure that it is held by the time the function returns */ +static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_pollset_worker **worker_hdl, + gpr_timespec now, gpr_timespec deadline) { + grpc_pollset_worker worker; + grpc_error *error = GRPC_ERROR_NONE; + static const char *err_desc = "pollset_work"; + if (pollset->kicked_without_poller) { + pollset->kicked_without_poller = false; + return GRPC_ERROR_NONE; + } + gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); + if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) { + gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); + GPR_ASSERT(!pollset->shutdown_closure); + GPR_ASSERT(!pollset->seen_inactive); + gpr_mu_unlock(&pollset->mu); + append_error(&error, pollset_epoll(exec_ctx, pollset, now, deadline), + err_desc); + gpr_mu_lock(&pollset->mu); + gpr_tls_set(&g_current_thread_worker, 0); + } + end_worker(exec_ctx, pollset, &worker, worker_hdl); + gpr_tls_set(&g_current_thread_pollset, 0); + return error; +} + +static grpc_error *pollset_kick(grpc_pollset *pollset, + grpc_pollset_worker *specific_worker) { + if (specific_worker == NULL) { + if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) { + grpc_pollset_worker *root_worker = pollset->root_worker; + if (root_worker == NULL) { + pollset->kicked_without_poller = true; + return GRPC_ERROR_NONE; + } + grpc_pollset_worker *next_worker = root_worker->next; + if (root_worker == next_worker && + root_worker == (grpc_pollset_worker *)gpr_atm_no_barrier_load( + &g_active_poller)) { + root_worker->kick_state = KICKED; + return grpc_wakeup_fd_wakeup(&global_wakeup_fd); + } else if (next_worker->kick_state == UNKICKED) { + GPR_ASSERT(next_worker->initialized_cv); + next_worker->kick_state = KICKED; + gpr_cv_signal(&next_worker->cv); + return GRPC_ERROR_NONE; + } else { + return GRPC_ERROR_NONE; + } + } else { + return GRPC_ERROR_NONE; + } + } else if (specific_worker->kick_state == KICKED) { + return GRPC_ERROR_NONE; + } else if (gpr_tls_get(&g_current_thread_worker) == + (intptr_t)specific_worker) { + specific_worker->kick_state = KICKED; + return GRPC_ERROR_NONE; + } else if (specific_worker == + (grpc_pollset_worker *)gpr_atm_no_barrier_load(&g_active_poller)) { + specific_worker->kick_state = KICKED; + return grpc_wakeup_fd_wakeup(&global_wakeup_fd); + } else if (specific_worker->initialized_cv) { + specific_worker->kick_state = KICKED; + gpr_cv_signal(&specific_worker->cv); + return GRPC_ERROR_NONE; + } else { + specific_worker->kick_state = KICKED; + return GRPC_ERROR_NONE; + } +} + +static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_fd *fd) {} + +/******************************************************************************* + * Workqueue Definitions + */ + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue, + const char *file, int line, + const char *reason) { + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, + const char *file, int line, const char *reason) {} +#else +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) { + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, + grpc_workqueue *workqueue) {} +#endif + +static void wq_sched(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error) { + // find a neighbourhood to wakeup + bool scheduled = false; + size_t initial_neighbourhood = choose_neighbourhood(); + for (size_t i = 0; !scheduled && i < g_num_neighbourhoods; i++) { + pollset_neighbourhood *neighbourhood = + &g_neighbourhoods[(initial_neighbourhood + i) % g_num_neighbourhoods]; + if (gpr_mu_trylock(&neighbourhood->mu)) { + if (neighbourhood->active_root != NULL) { + grpc_pollset *inspect = neighbourhood->active_root; + do { + if (gpr_mu_trylock(&inspect->mu)) { + if (inspect->root_worker != NULL) { + grpc_pollset_worker *inspect_worker = inspect->root_worker; + do { + if (inspect_worker->kick_state == UNKICKED) { + inspect_worker->kick_state = KICKED; + grpc_closure_list_append( + &inspect_worker->schedule_on_end_work, closure, error); + if (inspect_worker->initialized_cv) { + gpr_cv_signal(&inspect_worker->cv); + } + scheduled = true; + } + inspect_worker = inspect_worker->next; + } while (!scheduled && inspect_worker != inspect->root_worker); + } + gpr_mu_unlock(&inspect->mu); + } + inspect = inspect->next; + } while (!scheduled && inspect != neighbourhood->active_root); + } + gpr_mu_unlock(&neighbourhood->mu); + } + } + if (!scheduled) { + gpr_mu_lock(&g_wq_mu); + grpc_closure_list_append(&g_wq_items, closure, error); + gpr_mu_unlock(&g_wq_mu); + GRPC_LOG_IF_ERROR("workqueue_scheduler", + grpc_wakeup_fd_wakeup(&global_wakeup_fd)); + } +} + +static const grpc_closure_scheduler_vtable + singleton_workqueue_scheduler_vtable = {wq_sched, wq_sched, + "epoll1_workqueue"}; + +static grpc_closure_scheduler singleton_workqueue_scheduler = { + &singleton_workqueue_scheduler_vtable}; + +static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) { + return &singleton_workqueue_scheduler; +} + +/******************************************************************************* + * Pollset-set Definitions + */ + +static grpc_pollset_set *pollset_set_create(void) { + return (grpc_pollset_set *)((intptr_t)0xdeafbeef); +} + +static void pollset_set_destroy(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss) {} + +static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) {} + +static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) {} + +static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) {} + +static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) {} + +static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) {} + +static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) {} + +/******************************************************************************* + * Event engine binding + */ + +static void shutdown_engine(void) { + fd_global_shutdown(); + pollset_global_shutdown(); +} + +static const grpc_event_engine_vtable vtable = { + .pollset_size = sizeof(grpc_pollset), + + .fd_create = fd_create, + .fd_wrapped_fd = fd_wrapped_fd, + .fd_orphan = fd_orphan, + .fd_shutdown = fd_shutdown, + .fd_is_shutdown = fd_is_shutdown, + .fd_notify_on_read = fd_notify_on_read, + .fd_notify_on_write = fd_notify_on_write, + .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, + + .pollset_init = pollset_init, + .pollset_shutdown = pollset_shutdown, + .pollset_destroy = pollset_destroy, + .pollset_work = pollset_work, + .pollset_kick = pollset_kick, + .pollset_add_fd = pollset_add_fd, + + .pollset_set_create = pollset_set_create, + .pollset_set_destroy = pollset_set_destroy, + .pollset_set_add_pollset = pollset_set_add_pollset, + .pollset_set_del_pollset = pollset_set_del_pollset, + .pollset_set_add_pollset_set = pollset_set_add_pollset_set, + .pollset_set_del_pollset_set = pollset_set_del_pollset_set, + .pollset_set_add_fd = pollset_set_add_fd, + .pollset_set_del_fd = pollset_set_del_fd, + + .workqueue_ref = workqueue_ref, + .workqueue_unref = workqueue_unref, + .workqueue_scheduler = workqueue_scheduler, + + .shutdown_engine = shutdown_engine, +}; + +/* It is possible that GLIBC has epoll but the underlying kernel doesn't. + * Create a dummy epoll_fd to make sure epoll support is available */ +const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) { + /* TODO(ctiller): temporary, until this stabilizes */ + if (!explicit_request) return NULL; + + if (!grpc_has_wakeup_fd()) { + return NULL; + } + + g_epfd = epoll_create1(EPOLL_CLOEXEC); + if (g_epfd < 0) { + gpr_log(GPR_ERROR, "epoll unavailable"); + return NULL; + } + + fd_global_init(); + + if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { + close(g_epfd); + fd_global_shutdown(); + return NULL; + } + + return &vtable; +} + +#else /* defined(GRPC_LINUX_EPOLL) */ +#if defined(GRPC_POSIX_SOCKET) +#include "src/core/lib/iomgr/ev_posix.h" +/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return + * NULL */ +const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request) { + return NULL; +} +#endif /* defined(GRPC_POSIX_SOCKET) */ +#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/src/core/lib/iomgr/ev_epoll1_linux.h b/src/core/lib/iomgr/ev_epoll1_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..bd52478a7c176ab55e1f42166518e141d692f2f7 --- /dev/null +++ b/src/core/lib/iomgr/ev_epoll1_linux.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL1_LINUX_H +#define GRPC_CORE_LIB_IOMGR_EV_EPOLL1_LINUX_H + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/port.h" + +// a polling engine that utilizes a singleton epoll set and turnstile polling + +const grpc_event_engine_vtable *grpc_init_epoll1_linux(bool explicit_request); + +#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL1_LINUX_H */ diff --git a/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..d23bf6c06cbd72da21ff795491ba44eddbd9e4b4 --- /dev/null +++ b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c @@ -0,0 +1,2146 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +/* This polling engine is only relevant on linux kernels supporting epoll() */ +#ifdef GRPC_LINUX_EPOLL + +#include "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h" + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <poll.h> +#include <pthread.h> +#include <signal.h> +#include <string.h> +#include <sys/epoll.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/tls.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/lockfree_event.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/iomgr/workqueue.h" +#include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/block_annotate.h" +#include "src/core/lib/support/env.h" + +#define GRPC_POLLING_TRACE(fmt, ...) \ + if (GRPC_TRACER_ON(grpc_polling_trace)) { \ + gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \ + } + +#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) + +/* Uncomment the following to enable extra checks on poll_object operations */ +/* #define PO_DEBUG */ + +/* The maximum number of polling threads per polling island. By default no + limit */ +static int g_max_pollers_per_pi = INT_MAX; + +static int grpc_wakeup_signal = -1; +static bool is_grpc_wakeup_signal_initialized = false; + +/* Implements the function defined in grpc_posix.h. This function might be + * called before even calling grpc_init() to set either a different signal to + * use. If signum == -1, then the use of signals is disabled */ +static void grpc_use_signal(int signum) { + grpc_wakeup_signal = signum; + is_grpc_wakeup_signal_initialized = true; + + if (grpc_wakeup_signal < 0) { + gpr_log(GPR_INFO, + "Use of signals is disabled. Epoll engine will not be used"); + } else { + gpr_log(GPR_INFO, "epoll engine will be using signal: %d", + grpc_wakeup_signal); + } +} + +struct polling_island; + +typedef enum { + POLL_OBJ_FD, + POLL_OBJ_POLLSET, + POLL_OBJ_POLLSET_SET +} poll_obj_type; + +typedef struct poll_obj { +#ifdef PO_DEBUG + poll_obj_type obj_type; +#endif + gpr_mu mu; + struct polling_island *pi; +} poll_obj; + +static const char *poll_obj_string(poll_obj_type po_type) { + switch (po_type) { + case POLL_OBJ_FD: + return "fd"; + case POLL_OBJ_POLLSET: + return "pollset"; + case POLL_OBJ_POLLSET_SET: + return "pollset_set"; + } + + GPR_UNREACHABLE_CODE(return "UNKNOWN"); +} + +/******************************************************************************* + * Fd Declarations + */ + +#define FD_FROM_PO(po) ((grpc_fd *)(po)) + +struct grpc_fd { + poll_obj po; + + int fd; + /* refst format: + bit 0 : 1=Active / 0=Orphaned + bits 1-n : refcount + Ref/Unref by two to avoid altering the orphaned bit */ + gpr_atm refst; + + /* The fd is either closed or we relinquished control of it. In either + cases, this indicates that the 'fd' on this structure is no longer + valid */ + bool orphaned; + + gpr_atm read_closure; + gpr_atm write_closure; + + struct grpc_fd *freelist_next; + grpc_closure *on_done_closure; + + /* The pollset that last noticed that the fd is readable. The actual type + * stored in this is (grpc_pollset *) */ + gpr_atm read_notifier_pollset; + + grpc_iomgr_object iomgr_object; +}; + +/* Reference counting for fds */ +// #define GRPC_FD_REF_COUNT_DEBUG +#ifdef GRPC_FD_REF_COUNT_DEBUG +static void fd_ref(grpc_fd *fd, const char *reason, const char *file, int line); +static void fd_unref(grpc_fd *fd, const char *reason, const char *file, + int line); +#define GRPC_FD_REF(fd, reason) fd_ref(fd, reason, __FILE__, __LINE__) +#define GRPC_FD_UNREF(fd, reason) fd_unref(fd, reason, __FILE__, __LINE__) +#else +static void fd_ref(grpc_fd *fd); +static void fd_unref(grpc_fd *fd); +#define GRPC_FD_REF(fd, reason) fd_ref(fd) +#define GRPC_FD_UNREF(fd, reason) fd_unref(fd) +#endif + +static void fd_global_init(void); +static void fd_global_shutdown(void); + +/******************************************************************************* + * Polling island Declarations + */ + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG + +#define PI_ADD_REF(p, r) pi_add_ref_dbg((p), (r), __FILE__, __LINE__) +#define PI_UNREF(exec_ctx, p, r) \ + pi_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) + +#else /* defined(GRPC_WORKQUEUE_REFCOUNT_DEBUG) */ + +#define PI_ADD_REF(p, r) pi_add_ref((p)) +#define PI_UNREF(exec_ctx, p, r) pi_unref((exec_ctx), (p)) + +#endif /* !defined(GRPC_PI_REF_COUNT_DEBUG) */ + +typedef struct worker_node { + struct worker_node *next; + struct worker_node *prev; +} worker_node; + +/* This is also used as grpc_workqueue (by directly casing it) */ +typedef struct polling_island { + grpc_closure_scheduler workqueue_scheduler; + + gpr_mu mu; + /* Ref count. Use PI_ADD_REF() and PI_UNREF() macros to increment/decrement + the refcount. + Once the ref count becomes zero, this structure is destroyed which means + we should ensure that there is never a scenario where a PI_ADD_REF() is + racing with a PI_UNREF() that just made the ref_count zero. */ + gpr_atm ref_count; + + /* Pointer to the polling_island this merged into. + * merged_to value is only set once in polling_island's lifetime (and that too + * only if the island is merged with another island). Because of this, we can + * use gpr_atm type here so that we can do atomic access on this and reduce + * lock contention on 'mu' mutex. + * + * Note that if this field is not NULL (i.e not 0), all the remaining fields + * (except mu and ref_count) are invalid and must be ignored. */ + gpr_atm merged_to; + + /* Number of threads currently polling on this island */ + gpr_atm poller_count; + /* Mutex guarding the read end of the workqueue (must be held to pop from + * workqueue_items) */ + gpr_mu workqueue_read_mu; + /* Queue of closures to be executed */ + gpr_mpscq workqueue_items; + /* Count of items in workqueue_items */ + gpr_atm workqueue_item_count; + /* Wakeup fd used to wake pollers to check the contents of workqueue_items */ + grpc_wakeup_fd workqueue_wakeup_fd; + + /* The list of workers waiting to do polling on this polling island */ + gpr_mu worker_list_mu; + worker_node worker_list_head; + + /* The fd of the underlying epoll set */ + int epoll_fd; + + /* The file descriptors in the epoll set */ + size_t fd_cnt; + size_t fd_capacity; + grpc_fd **fds; +} polling_island; + +/******************************************************************************* + * Pollset Declarations + */ +#define WORKER_FROM_WORKER_LIST_NODE(p) \ + (struct grpc_pollset_worker *)(((char *)(p)) - \ + offsetof(grpc_pollset_worker, pi_list_link)) +struct grpc_pollset_worker { + /* Thread id of this worker */ + pthread_t pt_id; + + /* Used to prevent a worker from getting kicked multiple times */ + gpr_atm is_kicked; + + struct grpc_pollset_worker *next; + struct grpc_pollset_worker *prev; + + /* Indicates if it is this worker's turn to do epoll */ + gpr_atm is_polling_turn; + + /* Node in the polling island's worker list. */ + worker_node pi_list_link; +}; + +struct grpc_pollset { + poll_obj po; + + grpc_pollset_worker root_worker; + bool kicked_without_pollers; + + bool shutting_down; /* Is the pollset shutting down ? */ + bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ + grpc_closure *shutdown_done; /* Called after after shutdown is complete */ +}; + +/******************************************************************************* + * Pollset-set Declarations + */ +struct grpc_pollset_set { + poll_obj po; +}; + +/******************************************************************************* + * Common helpers + */ + +static bool append_error(grpc_error **composite, grpc_error *error, + const char *desc) { + if (error == GRPC_ERROR_NONE) return true; + if (*composite == GRPC_ERROR_NONE) { + *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); + } + *composite = grpc_error_add_child(*composite, error); + return false; +} + +/******************************************************************************* + * Polling island Definitions + */ + +/* The wakeup fd that is used to wake up all threads in a Polling island. This + is useful in the polling island merge operation where we need to wakeup all + the threads currently polling the smaller polling island (so that they can + start polling the new/merged polling island) + + NOTE: This fd is initialized to be readable and MUST NOT be consumed i.e the + threads that woke up MUST NOT call grpc_wakeup_fd_consume_wakeup() */ +static grpc_wakeup_fd polling_island_wakeup_fd; + +/* The polling island being polled right now. + See comments in workqueue_maybe_wakeup for why this is tracked. */ +static __thread polling_island *g_current_thread_polling_island; + +/* Forward declaration */ +static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi); +static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error); + +#ifdef GRPC_TSAN +/* Currently TSAN may incorrectly flag data races between epoll_ctl and + epoll_wait for any grpc_fd structs that are added to the epoll set via + epoll_ctl and are returned (within a very short window) via epoll_wait(). + + To work-around this race, we establish a happens-before relation between + the code just-before epoll_ctl() and the code after epoll_wait() by using + this atomic */ +gpr_atm g_epoll_sync; +#endif /* defined(GRPC_TSAN) */ + +static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = { + workqueue_enqueue, workqueue_enqueue, "workqueue"}; + +static void pi_add_ref(polling_island *pi); +static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi); + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG +static void pi_add_ref_dbg(polling_island *pi, const char *reason, + const char *file, int line) { + long old_cnt = gpr_atm_acq_load(&pi->ref_count); + pi_add_ref(pi); + gpr_log(GPR_DEBUG, "Add ref pi: %p, old: %ld -> new:%ld (%s) - (%s, %d)", + (void *)pi, old_cnt, old_cnt + 1, reason, file, line); +} + +static void pi_unref_dbg(grpc_exec_ctx *exec_ctx, polling_island *pi, + const char *reason, const char *file, int line) { + long old_cnt = gpr_atm_acq_load(&pi->ref_count); + pi_unref(exec_ctx, pi); + gpr_log(GPR_DEBUG, "Unref pi: %p, old:%ld -> new:%ld (%s) - (%s, %d)", + (void *)pi, old_cnt, (old_cnt - 1), reason, file, line); +} + +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue, + const char *file, int line, + const char *reason) { + if (workqueue != NULL) { + pi_add_ref_dbg((polling_island *)workqueue, reason, file, line); + } + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, + const char *file, int line, const char *reason) { + if (workqueue != NULL) { + pi_unref_dbg(exec_ctx, (polling_island *)workqueue, reason, file, line); + } +} +#else +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) { + if (workqueue != NULL) { + pi_add_ref((polling_island *)workqueue); + } + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, + grpc_workqueue *workqueue) { + if (workqueue != NULL) { + pi_unref(exec_ctx, (polling_island *)workqueue); + } +} +#endif + +static void pi_add_ref(polling_island *pi) { + gpr_atm_no_barrier_fetch_add(&pi->ref_count, 1); +} + +static void pi_unref(grpc_exec_ctx *exec_ctx, polling_island *pi) { + /* If ref count went to zero, delete the polling island. + Note that this deletion not be done under a lock. Once the ref count goes + to zero, we are guaranteed that no one else holds a reference to the + polling island (and that there is no racing pi_add_ref() call either). + + Also, if we are deleting the polling island and the merged_to field is + non-empty, we should remove a ref to the merged_to polling island + */ + if (1 == gpr_atm_full_fetch_add(&pi->ref_count, -1)) { + polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); + polling_island_delete(exec_ctx, pi); + if (next != NULL) { + PI_UNREF(exec_ctx, next, "pi_delete"); /* Recursive call */ + } + } +} + +static void worker_node_init(worker_node *node) { + node->next = node->prev = node; +} + +/* Not thread safe. Do under a list-level lock */ +static void push_back_worker_node(worker_node *head, worker_node *node) { + node->next = head; + node->prev = head->prev; + head->prev->next = node; + head->prev = node; +} + +/* Not thread safe. Do under a list-level lock */ +static void remove_worker_node(worker_node *node) { + node->next->prev = node->prev; + node->prev->next = node->next; + /* If node's next and prev point to itself, the node is considered detached + * from the list*/ + node->next = node->prev = node; +} + +/* Not thread safe. Do under a list-level lock */ +static worker_node *pop_front_worker_node(worker_node *head) { + worker_node *node = head->next; + if (node != head) { + remove_worker_node(node); + } else { + node = NULL; + } + + return node; +} + +/* Returns true if the node's next and prev are pointing to itself (which + indicates that the node is not in the list */ +static bool is_worker_node_detached(worker_node *node) { + return (node->next == node->prev && node->next == node); +} + +/* The caller is expected to hold pi->mu lock before calling this function + */ +static void polling_island_add_fds_locked(polling_island *pi, grpc_fd **fds, + size_t fd_count, bool add_fd_refs, + grpc_error **error) { + int err; + size_t i; + struct epoll_event ev; + char *err_msg; + const char *err_desc = "polling_island_add_fds"; + +#ifdef GRPC_TSAN + /* See the definition of g_epoll_sync for more context */ + gpr_atm_rel_store(&g_epoll_sync, (gpr_atm)0); +#endif /* defined(GRPC_TSAN) */ + + for (i = 0; i < fd_count; i++) { + ev.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET); + ev.data.ptr = fds[i]; + err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, fds[i]->fd, &ev); + + if (err < 0) { + if (errno != EEXIST) { + gpr_asprintf( + &err_msg, + "epoll_ctl (epoll_fd: %d) add fd: %d failed with error: %d (%s)", + pi->epoll_fd, fds[i]->fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } + + continue; + } + + if (pi->fd_cnt == pi->fd_capacity) { + pi->fd_capacity = GPR_MAX(pi->fd_capacity + 8, pi->fd_cnt * 3 / 2); + pi->fds = gpr_realloc(pi->fds, sizeof(grpc_fd *) * pi->fd_capacity); + } + + pi->fds[pi->fd_cnt++] = fds[i]; + if (add_fd_refs) { + GRPC_FD_REF(fds[i], "polling_island"); + } + } +} + +/* The caller is expected to hold pi->mu before calling this */ +static void polling_island_add_wakeup_fd_locked(polling_island *pi, + grpc_wakeup_fd *wakeup_fd, + grpc_error **error) { + struct epoll_event ev; + int err; + char *err_msg; + const char *err_desc = "polling_island_add_wakeup_fd"; + + ev.events = (uint32_t)(EPOLLIN | EPOLLET); + ev.data.ptr = wakeup_fd; + err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_ADD, + GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), &ev); + if (err < 0 && errno != EEXIST) { + gpr_asprintf(&err_msg, + "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with " + "error: %d (%s)", + pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), errno, + strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } +} + +/* The caller is expected to hold pi->mu lock before calling this function */ +static void polling_island_remove_all_fds_locked(polling_island *pi, + bool remove_fd_refs, + grpc_error **error) { + int err; + size_t i; + char *err_msg; + const char *err_desc = "polling_island_remove_fds"; + + for (i = 0; i < pi->fd_cnt; i++) { + err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, pi->fds[i]->fd, NULL); + if (err < 0 && errno != ENOENT) { + gpr_asprintf(&err_msg, + "epoll_ctl (epoll_fd: %d) delete fds[%zu]: %d failed with " + "error: %d (%s)", + pi->epoll_fd, i, pi->fds[i]->fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } + + if (remove_fd_refs) { + GRPC_FD_UNREF(pi->fds[i], "polling_island"); + } + } + + pi->fd_cnt = 0; +} + +/* The caller is expected to hold pi->mu lock before calling this function */ +static void polling_island_remove_fd_locked(polling_island *pi, grpc_fd *fd, + bool is_fd_closed, + grpc_error **error) { + int err; + size_t i; + char *err_msg; + const char *err_desc = "polling_island_remove_fd"; + + /* If fd is already closed, then it would have been automatically been removed + from the epoll set */ + if (!is_fd_closed) { + err = epoll_ctl(pi->epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL); + if (err < 0 && errno != ENOENT) { + gpr_asprintf( + &err_msg, + "epoll_ctl (epoll_fd: %d) del fd: %d failed with error: %d (%s)", + pi->epoll_fd, fd->fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } + } + + for (i = 0; i < pi->fd_cnt; i++) { + if (pi->fds[i] == fd) { + pi->fds[i] = pi->fds[--pi->fd_cnt]; + GRPC_FD_UNREF(fd, "polling_island"); + break; + } + } +} + +/* Might return NULL in case of an error */ +static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx, + grpc_fd *initial_fd, + grpc_error **error) { + polling_island *pi = NULL; + const char *err_desc = "polling_island_create"; + + *error = GRPC_ERROR_NONE; + + pi = gpr_malloc(sizeof(*pi)); + pi->workqueue_scheduler.vtable = &workqueue_scheduler_vtable; + gpr_mu_init(&pi->mu); + pi->fd_cnt = 0; + pi->fd_capacity = 0; + pi->fds = NULL; + pi->epoll_fd = -1; + + gpr_mu_init(&pi->workqueue_read_mu); + gpr_mpscq_init(&pi->workqueue_items); + gpr_atm_rel_store(&pi->workqueue_item_count, 0); + + gpr_atm_rel_store(&pi->ref_count, 0); + gpr_atm_rel_store(&pi->poller_count, 0); + gpr_atm_rel_store(&pi->merged_to, (gpr_atm)NULL); + + gpr_mu_init(&pi->worker_list_mu); + worker_node_init(&pi->worker_list_head); + + if (!append_error(error, grpc_wakeup_fd_init(&pi->workqueue_wakeup_fd), + err_desc)) { + goto done; + } + + pi->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + + if (pi->epoll_fd < 0) { + append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc); + goto done; + } + + polling_island_add_wakeup_fd_locked(pi, &pi->workqueue_wakeup_fd, error); + + if (initial_fd != NULL) { + polling_island_add_fds_locked(pi, &initial_fd, 1, true, error); + } + +done: + if (*error != GRPC_ERROR_NONE) { + polling_island_delete(exec_ctx, pi); + pi = NULL; + } + return pi; +} + +static void polling_island_delete(grpc_exec_ctx *exec_ctx, polling_island *pi) { + GPR_ASSERT(pi->fd_cnt == 0); + + if (pi->epoll_fd >= 0) { + close(pi->epoll_fd); + } + GPR_ASSERT(gpr_atm_no_barrier_load(&pi->workqueue_item_count) == 0); + gpr_mu_destroy(&pi->workqueue_read_mu); + gpr_mpscq_destroy(&pi->workqueue_items); + gpr_mu_destroy(&pi->mu); + grpc_wakeup_fd_destroy(&pi->workqueue_wakeup_fd); + gpr_mu_destroy(&pi->worker_list_mu); + GPR_ASSERT(is_worker_node_detached(&pi->worker_list_head)); + + gpr_free(pi->fds); + gpr_free(pi); +} + +/* Attempts to gets the last polling island in the linked list (liked by the + * 'merged_to' field). Since this does not lock the polling island, there are no + * guarantees that the island returned is the last island */ +static polling_island *polling_island_maybe_get_latest(polling_island *pi) { + polling_island *next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); + while (next != NULL) { + pi = next; + next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); + } + + return pi; +} + +/* Gets the lock on the *latest* polling island i.e the last polling island in + the linked list (linked by the 'merged_to' field). Call gpr_mu_unlock on the + returned polling island's mu. + Usage: To lock/unlock polling island "pi", do the following: + polling_island *pi_latest = polling_island_lock(pi); + ... + ... critical section .. + ... + gpr_mu_unlock(&pi_latest->mu); // NOTE: use pi_latest->mu. NOT pi->mu */ +static polling_island *polling_island_lock(polling_island *pi) { + polling_island *next = NULL; + + while (true) { + next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); + if (next == NULL) { + /* Looks like 'pi' is the last node in the linked list but unless we check + this by holding the pi->mu lock, we cannot be sure (i.e without the + pi->mu lock, we don't prevent island merges). + To be absolutely sure, check once more by holding the pi->mu lock */ + gpr_mu_lock(&pi->mu); + next = (polling_island *)gpr_atm_acq_load(&pi->merged_to); + if (next == NULL) { + /* pi is infact the last node and we have the pi->mu lock. we're done */ + break; + } + + /* pi->merged_to is not NULL i.e pi isn't the last node anymore. pi->mu + * isn't the lock we are interested in. Continue traversing the list */ + gpr_mu_unlock(&pi->mu); + } + + pi = next; + } + + return pi; +} + +/* Gets the lock on the *latest* polling islands in the linked lists pointed by + *p and *q (and also updates *p and *q to point to the latest polling islands) + + This function is needed because calling the following block of code to obtain + locks on polling islands (*p and *q) is prone to deadlocks. + { + polling_island_lock(*p, true); + polling_island_lock(*q, true); + } + + Usage/example: + polling_island *p1; + polling_island *p2; + .. + polling_island_lock_pair(&p1, &p2); + .. + .. Critical section with both p1 and p2 locked + .. + // Release locks: Always call polling_island_unlock_pair() to release locks + polling_island_unlock_pair(p1, p2); +*/ +static void polling_island_lock_pair(polling_island **p, polling_island **q) { + polling_island *pi_1 = *p; + polling_island *pi_2 = *q; + polling_island *next_1 = NULL; + polling_island *next_2 = NULL; + + /* The algorithm is simple: + - Go to the last polling islands in the linked lists *pi_1 and *pi_2 (and + keep updating pi_1 and pi_2) + - Then obtain locks on the islands by following a lock order rule of + locking polling_island with lower address first + Special case: Before obtaining the locks, check if pi_1 and pi_2 are + pointing to the same island. If that is the case, we can just call + polling_island_lock() + - After obtaining both the locks, double check that the polling islands + are still the last polling islands in their respective linked lists + (this is because there might have been polling island merges before + we got the lock) + - If the polling islands are the last islands, we are done. If not, + release the locks and continue the process from the first step */ + while (true) { + next_1 = (polling_island *)gpr_atm_acq_load(&pi_1->merged_to); + while (next_1 != NULL) { + pi_1 = next_1; + next_1 = (polling_island *)gpr_atm_acq_load(&pi_1->merged_to); + } + + next_2 = (polling_island *)gpr_atm_acq_load(&pi_2->merged_to); + while (next_2 != NULL) { + pi_2 = next_2; + next_2 = (polling_island *)gpr_atm_acq_load(&pi_2->merged_to); + } + + if (pi_1 == pi_2) { + pi_1 = pi_2 = polling_island_lock(pi_1); + break; + } + + if (pi_1 < pi_2) { + gpr_mu_lock(&pi_1->mu); + gpr_mu_lock(&pi_2->mu); + } else { + gpr_mu_lock(&pi_2->mu); + gpr_mu_lock(&pi_1->mu); + } + + next_1 = (polling_island *)gpr_atm_acq_load(&pi_1->merged_to); + next_2 = (polling_island *)gpr_atm_acq_load(&pi_2->merged_to); + if (next_1 == NULL && next_2 == NULL) { + break; + } + + gpr_mu_unlock(&pi_1->mu); + gpr_mu_unlock(&pi_2->mu); + } + + *p = pi_1; + *q = pi_2; +} + +static void polling_island_unlock_pair(polling_island *p, polling_island *q) { + if (p == q) { + gpr_mu_unlock(&p->mu); + } else { + gpr_mu_unlock(&p->mu); + gpr_mu_unlock(&q->mu); + } +} + +static void workqueue_maybe_wakeup(polling_island *pi) { + /* If this thread is the current poller, then it may be that it's about to + decrement the current poller count, so we need to look past this thread */ + bool is_current_poller = (g_current_thread_polling_island == pi); + gpr_atm min_current_pollers_for_wakeup = is_current_poller ? 1 : 0; + gpr_atm current_pollers = gpr_atm_no_barrier_load(&pi->poller_count); + /* Only issue a wakeup if it's likely that some poller could come in and take + it right now. Note that since we do an anticipatory mpscq_pop every poll + loop, it's ok if we miss the wakeup here, as we'll get the work item when + the next poller enters anyway. */ + if (current_pollers > min_current_pollers_for_wakeup) { + GRPC_LOG_IF_ERROR("workqueue_wakeup_fd", + grpc_wakeup_fd_wakeup(&pi->workqueue_wakeup_fd)); + } +} + +static void workqueue_move_items_to_parent(polling_island *q) { + polling_island *p = (polling_island *)gpr_atm_no_barrier_load(&q->merged_to); + if (p == NULL) { + return; + } + gpr_mu_lock(&q->workqueue_read_mu); + int num_added = 0; + while (gpr_atm_no_barrier_load(&q->workqueue_item_count) > 0) { + gpr_mpscq_node *n = gpr_mpscq_pop(&q->workqueue_items); + if (n != NULL) { + gpr_atm_no_barrier_fetch_add(&q->workqueue_item_count, -1); + gpr_atm_no_barrier_fetch_add(&p->workqueue_item_count, 1); + gpr_mpscq_push(&p->workqueue_items, n); + num_added++; + } + } + gpr_mu_unlock(&q->workqueue_read_mu); + if (num_added > 0) { + workqueue_maybe_wakeup(p); + } + workqueue_move_items_to_parent(p); +} + +static polling_island *polling_island_merge(polling_island *p, + polling_island *q, + grpc_error **error) { + /* Get locks on both the polling islands */ + polling_island_lock_pair(&p, &q); + + if (p != q) { + /* Make sure that p points to the polling island with fewer fds than q */ + if (p->fd_cnt > q->fd_cnt) { + GPR_SWAP(polling_island *, p, q); + } + + /* Merge p with q i.e move all the fds from p (The one with fewer fds) to q + Note that the refcounts on the fds being moved will not change here. + This is why the last param in the following two functions is 'false') */ + polling_island_add_fds_locked(q, p->fds, p->fd_cnt, false, error); + polling_island_remove_all_fds_locked(p, false, error); + + /* Wakeup all the pollers (if any) on p so that they pickup this change */ + polling_island_add_wakeup_fd_locked(p, &polling_island_wakeup_fd, error); + + /* Add the 'merged_to' link from p --> q */ + gpr_atm_rel_store(&p->merged_to, (gpr_atm)q); + PI_ADD_REF(q, "pi_merge"); /* To account for the new incoming ref from p */ + + workqueue_move_items_to_parent(p); + } + /* else if p == q, nothing needs to be done */ + + polling_island_unlock_pair(p, q); + + /* Return the merged polling island (Note that no merge would have happened + if p == q which is ok) */ + return q; +} + +static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error) { + GPR_TIMER_BEGIN("workqueue.enqueue", 0); + grpc_workqueue *workqueue = (grpc_workqueue *)closure->scheduler; + /* take a ref to the workqueue: otherwise it can happen that whatever events + * this kicks off ends up destroying the workqueue before this function + * completes */ + GRPC_WORKQUEUE_REF(workqueue, "enqueue"); + polling_island *pi = (polling_island *)workqueue; + gpr_atm last = gpr_atm_no_barrier_fetch_add(&pi->workqueue_item_count, 1); + closure->error_data.error = error; + gpr_mpscq_push(&pi->workqueue_items, &closure->next_data.atm_next); + if (last == 0) { + workqueue_maybe_wakeup(pi); + } + workqueue_move_items_to_parent(pi); + GRPC_WORKQUEUE_UNREF(exec_ctx, workqueue, "enqueue"); + GPR_TIMER_END("workqueue.enqueue", 0); +} + +static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) { + polling_island *pi = (polling_island *)workqueue; + return workqueue == NULL ? grpc_schedule_on_exec_ctx + : &pi->workqueue_scheduler; +} + +static grpc_error *polling_island_global_init() { + grpc_error *error = GRPC_ERROR_NONE; + + error = grpc_wakeup_fd_init(&polling_island_wakeup_fd); + if (error == GRPC_ERROR_NONE) { + error = grpc_wakeup_fd_wakeup(&polling_island_wakeup_fd); + } + + return error; +} + +static void polling_island_global_shutdown() { + grpc_wakeup_fd_destroy(&polling_island_wakeup_fd); +} + +/******************************************************************************* + * Fd Definitions + */ + +/* We need to keep a freelist not because of any concerns of malloc performance + * but instead so that implementations with multiple threads in (for example) + * epoll_wait deal with the race between pollset removal and incoming poll + * notifications. + * + * The problem is that the poller ultimately holds a reference to this + * object, so it is very difficult to know when is safe to free it, at least + * without some expensive synchronization. + * + * If we keep the object freelisted, in the worst case losing this race just + * becomes a spurious read notification on a reused fd. + */ + +/* The alarm system needs to be able to wakeup 'some poller' sometimes + * (specifically when a new alarm needs to be triggered earlier than the next + * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a + * case occurs. */ + +static grpc_fd *fd_freelist = NULL; +static gpr_mu fd_freelist_mu; + +#ifdef GRPC_FD_REF_COUNT_DEBUG +#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) +#define UNREF_BY(fd, n, reason) unref_by(fd, n, reason, __FILE__, __LINE__) +static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, + int line) { + gpr_log(GPR_DEBUG, "FD %d %p ref %d %ld -> %ld [%s; %s:%d]", fd->fd, + (void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), + gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); +#else +#define REF_BY(fd, n, reason) ref_by(fd, n) +#define UNREF_BY(fd, n, reason) unref_by(fd, n) +static void ref_by(grpc_fd *fd, int n) { +#endif + GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); +} + +#ifdef GRPC_FD_REF_COUNT_DEBUG +static void unref_by(grpc_fd *fd, int n, const char *reason, const char *file, + int line) { + gpr_atm old; + gpr_log(GPR_DEBUG, "FD %d %p unref %d %ld -> %ld [%s; %s:%d]", fd->fd, + (void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), + gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); +#else +static void unref_by(grpc_fd *fd, int n) { + gpr_atm old; +#endif + old = gpr_atm_full_fetch_add(&fd->refst, -n); + if (old == n) { + /* Add the fd to the freelist */ + gpr_mu_lock(&fd_freelist_mu); + fd->freelist_next = fd_freelist; + fd_freelist = fd; + grpc_iomgr_unregister_object(&fd->iomgr_object); + + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); + + gpr_mu_unlock(&fd_freelist_mu); + } else { + GPR_ASSERT(old > n); + } +} + +/* Increment refcount by two to avoid changing the orphan bit */ +#ifdef GRPC_FD_REF_COUNT_DEBUG +static void fd_ref(grpc_fd *fd, const char *reason, const char *file, + int line) { + ref_by(fd, 2, reason, file, line); +} + +static void fd_unref(grpc_fd *fd, const char *reason, const char *file, + int line) { + unref_by(fd, 2, reason, file, line); +} +#else +static void fd_ref(grpc_fd *fd) { ref_by(fd, 2); } +static void fd_unref(grpc_fd *fd) { unref_by(fd, 2); } +#endif + +static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } + +static void fd_global_shutdown(void) { + gpr_mu_lock(&fd_freelist_mu); + gpr_mu_unlock(&fd_freelist_mu); + while (fd_freelist != NULL) { + grpc_fd *fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + gpr_mu_destroy(&fd->po.mu); + gpr_free(fd); + } + gpr_mu_destroy(&fd_freelist_mu); +} + +static grpc_fd *fd_create(int fd, const char *name) { + grpc_fd *new_fd = NULL; + + gpr_mu_lock(&fd_freelist_mu); + if (fd_freelist != NULL) { + new_fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + } + gpr_mu_unlock(&fd_freelist_mu); + + if (new_fd == NULL) { + new_fd = gpr_malloc(sizeof(grpc_fd)); + gpr_mu_init(&new_fd->po.mu); + } + + /* Note: It is not really needed to get the new_fd->po.mu lock here. If this + * is a newly created fd (or an fd we got from the freelist), no one else + * would be holding a lock to it anyway. */ + gpr_mu_lock(&new_fd->po.mu); + new_fd->po.pi = NULL; +#ifdef PO_DEBUG + new_fd->po.obj_type = POLL_OBJ_FD; +#endif + + gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); + new_fd->fd = fd; + new_fd->orphaned = false; + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); + gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); + + new_fd->freelist_next = NULL; + new_fd->on_done_closure = NULL; + + gpr_mu_unlock(&new_fd->po.mu); + + char *fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); +#ifdef GRPC_FD_REF_COUNT_DEBUG + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); +#endif + gpr_free(fd_name); + return new_fd; +} + +static int fd_wrapped_fd(grpc_fd *fd) { + int ret_fd = -1; + gpr_mu_lock(&fd->po.mu); + if (!fd->orphaned) { + ret_fd = fd->fd; + } + gpr_mu_unlock(&fd->po.mu); + + return ret_fd; +} + +static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *on_done, int *release_fd, + const char *reason) { + bool is_fd_closed = false; + grpc_error *error = GRPC_ERROR_NONE; + polling_island *unref_pi = NULL; + + gpr_mu_lock(&fd->po.mu); + fd->on_done_closure = on_done; + + /* If release_fd is not NULL, we should be relinquishing control of the file + descriptor fd->fd (but we still own the grpc_fd structure). */ + if (release_fd != NULL) { + *release_fd = fd->fd; + } else { + close(fd->fd); + is_fd_closed = true; + } + + fd->orphaned = true; + + /* Remove the active status but keep referenced. We want this grpc_fd struct + to be alive (and not added to freelist) until the end of this function */ + REF_BY(fd, 1, reason); + + /* Remove the fd from the polling island: + - Get a lock on the latest polling island (i.e the last island in the + linked list pointed by fd->po.pi). This is the island that + would actually contain the fd + - Remove the fd from the latest polling island + - Unlock the latest polling island + - Set fd->po.pi to NULL (but remove the ref on the polling island + before doing this.) */ + if (fd->po.pi != NULL) { + polling_island *pi_latest = polling_island_lock(fd->po.pi); + polling_island_remove_fd_locked(pi_latest, fd, is_fd_closed, &error); + gpr_mu_unlock(&pi_latest->mu); + + unref_pi = fd->po.pi; + fd->po.pi = NULL; + } + + grpc_closure_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error)); + + gpr_mu_unlock(&fd->po.mu); + UNREF_BY(fd, 2, reason); /* Drop the reference */ + if (unref_pi != NULL) { + /* Unref stale polling island here, outside the fd lock above. + The polling island owns a workqueue which owns an fd, and unreffing + inside the lock can cause an eventual lock loop that makes TSAN very + unhappy. */ + PI_UNREF(exec_ctx, unref_pi, "fd_orphan"); + } + GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error)); + GRPC_ERROR_UNREF(error); +} + +static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, + grpc_fd *fd) { + gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); + return (grpc_pollset *)notifier; +} + +static bool fd_is_shutdown(grpc_fd *fd) { + return grpc_lfev_is_shutdown(&fd->read_closure); +} + +/* Might be called multiple times */ +static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { + shutdown(fd->fd, SHUT_RDWR); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + } + GRPC_ERROR_UNREF(why); +} + +static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure); +} + +static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure); +} + +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { + gpr_mu_lock(&fd->po.mu); + grpc_workqueue *workqueue = + GRPC_WORKQUEUE_REF((grpc_workqueue *)fd->po.pi, "fd_get_workqueue"); + gpr_mu_unlock(&fd->po.mu); + return workqueue; +} + +/******************************************************************************* + * Pollset Definitions + */ +GPR_TLS_DECL(g_current_thread_pollset); +GPR_TLS_DECL(g_current_thread_worker); +static __thread bool g_initialized_sigmask; +static __thread sigset_t g_orig_sigmask; +static __thread sigset_t g_wakeup_sig_set; + +static void sig_handler(int sig_num) { +#ifdef GRPC_EPOLL_DEBUG + gpr_log(GPR_INFO, "Received signal %d", sig_num); +#endif +} + +static void pollset_worker_init(grpc_pollset_worker *worker) { + worker->pt_id = pthread_self(); + worker->next = worker->prev = NULL; + gpr_atm_no_barrier_store(&worker->is_kicked, (gpr_atm)0); + gpr_atm_no_barrier_store(&worker->is_polling_turn, (gpr_atm)0); + worker_node_init(&worker->pi_list_link); +} + +static void poller_kick_init() { signal(grpc_wakeup_signal, sig_handler); } + +/* Global state management */ +static grpc_error *pollset_global_init(void) { + gpr_tls_init(&g_current_thread_pollset); + gpr_tls_init(&g_current_thread_worker); + poller_kick_init(); + return GRPC_ERROR_NONE; +} + +static void pollset_global_shutdown(void) { + gpr_tls_destroy(&g_current_thread_pollset); + gpr_tls_destroy(&g_current_thread_worker); +} + +static grpc_error *worker_kick(grpc_pollset_worker *worker, + gpr_atm *is_kicked) { + grpc_error *err = GRPC_ERROR_NONE; + + /* Kick the worker only if it was not already kicked */ + if (gpr_atm_no_barrier_cas(is_kicked, (gpr_atm)0, (gpr_atm)1)) { + GRPC_POLLING_TRACE( + "pollset_worker_kick: Kicking worker: %p (thread id: %ld)", + (void *)worker, (long int)worker->pt_id); + int err_num = pthread_kill(worker->pt_id, grpc_wakeup_signal); + if (err_num != 0) { + err = GRPC_OS_ERROR(err_num, "pthread_kill"); + } + } + return err; +} + +static grpc_error *pollset_worker_kick(grpc_pollset_worker *worker) { + return worker_kick(worker, &worker->is_kicked); +} + +static grpc_error *poller_kick(grpc_pollset_worker *worker) { + return worker_kick(worker, &worker->is_polling_turn); +} + +/* Return 1 if the pollset has active threads in pollset_work (pollset must + * be locked) */ +static int pollset_has_workers(grpc_pollset *p) { + return p->root_worker.next != &p->root_worker; +} + +static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) { + worker->prev->next = worker->next; + worker->next->prev = worker->prev; +} + +static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { + if (pollset_has_workers(p)) { + grpc_pollset_worker *w = p->root_worker.next; + remove_worker(p, w); + return w; + } else { + return NULL; + } +} + +static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) { + worker->next = &p->root_worker; + worker->prev = worker->next->prev; + worker->prev->next = worker->next->prev = worker; +} + +static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) { + worker->prev = &p->root_worker; + worker->next = worker->prev->next; + worker->prev->next = worker->next->prev = worker; +} + +/* p->mu must be held before calling this function */ +static grpc_error *pollset_kick(grpc_pollset *p, + grpc_pollset_worker *specific_worker) { + GPR_TIMER_BEGIN("pollset_kick", 0); + grpc_error *error = GRPC_ERROR_NONE; + const char *err_desc = "Kick Failure"; + grpc_pollset_worker *worker = specific_worker; + if (worker != NULL) { + if (worker == GRPC_POLLSET_KICK_BROADCAST) { + if (pollset_has_workers(p)) { + GPR_TIMER_BEGIN("pollset_kick.broadcast", 0); + for (worker = p->root_worker.next; worker != &p->root_worker; + worker = worker->next) { + if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { + append_error(&error, pollset_worker_kick(worker), err_desc); + } + } + GPR_TIMER_END("pollset_kick.broadcast", 0); + } else { + p->kicked_without_pollers = true; + } + } else { + GPR_TIMER_MARK("kicked_specifically", 0); + if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { + append_error(&error, pollset_worker_kick(worker), err_desc); + } + } + } else if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)p) { + /* Since worker == NULL, it means that we can kick "any" worker on this + pollset 'p'. If 'p' happens to be the same pollset this thread is + currently polling (i.e in pollset_work() function), then there is no need + to kick any other worker since the current thread can just absorb the + kick. This is the reason why we enter this case only when + g_current_thread_pollset is != p */ + + GPR_TIMER_MARK("kick_anonymous", 0); + worker = pop_front_worker(p); + if (worker != NULL) { + GPR_TIMER_MARK("finally_kick", 0); + push_back_worker(p, worker); + append_error(&error, pollset_worker_kick(worker), err_desc); + } else { + GPR_TIMER_MARK("kicked_no_pollers", 0); + p->kicked_without_pollers = true; + } + } + + GPR_TIMER_END("pollset_kick", 0); + GRPC_LOG_IF_ERROR("pollset_kick", GRPC_ERROR_REF(error)); + return error; +} + +static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { + gpr_mu_init(&pollset->po.mu); + *mu = &pollset->po.mu; + pollset->po.pi = NULL; +#ifdef PO_DEBUG + pollset->po.obj_type = POLL_OBJ_POLLSET; +#endif + + pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; + pollset->kicked_without_pollers = false; + + pollset->shutting_down = false; + pollset->finish_shutdown_called = false; + pollset->shutdown_done = NULL; +} + +/* Convert millis to timespec (clock-type is assumed to be GPR_TIMESPAN) */ +static struct timespec millis_to_timespec(int millis) { + struct timespec linux_ts; + gpr_timespec gpr_ts; + + if (millis == -1) { + gpr_ts = gpr_inf_future(GPR_TIMESPAN); + } else { + gpr_ts = gpr_time_from_millis(millis, GPR_TIMESPAN); + } + + linux_ts.tv_sec = (time_t)gpr_ts.tv_sec; + linux_ts.tv_nsec = gpr_ts.tv_nsec; + return linux_ts; +} + +/* Convert a timespec to milliseconds: + - Very small or negative poll times are clamped to zero to do a non-blocking + poll (which becomes spin polling) + - Other small values are rounded up to one millisecond + - Longer than a millisecond polls are rounded up to the next nearest + millisecond to avoid spinning + - Infinite timeouts are converted to -1 */ +static int poll_deadline_to_millis_timeout(gpr_timespec deadline, + gpr_timespec now) { + gpr_timespec timeout; + static const int64_t max_spin_polling_us = 10; + if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { + return -1; + } + + if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros( + max_spin_polling_us, + GPR_TIMESPAN))) <= 0) { + return 0; + } + timeout = gpr_time_sub(deadline, now); + int millis = gpr_time_to_millis(gpr_time_add( + timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN))); + return millis >= 1 ? millis : 1; +} + +static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_pollset *notifier) { + grpc_lfev_set_ready(exec_ctx, &fd->read_closure); + + /* Note, it is possible that fd_become_readable might be called twice with + different 'notifier's when an fd becomes readable and it is in two epoll + sets (This can happen briefly during polling island merges). In such cases + it does not really matter which notifer is set as the read_notifier_pollset + (They would both point to the same polling island anyway) */ + /* Use release store to match with acquire load in fd_get_read_notifier */ + gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); +} + +static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { + grpc_lfev_set_ready(exec_ctx, &fd->write_closure); +} + +static void pollset_release_polling_island(grpc_exec_ctx *exec_ctx, + grpc_pollset *ps, char *reason) { + if (ps->po.pi != NULL) { + PI_UNREF(exec_ctx, ps->po.pi, reason); + } + ps->po.pi = NULL; +} + +static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset) { + /* The pollset cannot have any workers if we are at this stage */ + GPR_ASSERT(!pollset_has_workers(pollset)); + + pollset->finish_shutdown_called = true; + + /* Release the ref and set pollset->po.pi to NULL */ + pollset_release_polling_island(exec_ctx, pollset, "ps_shutdown"); + grpc_closure_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE); +} + +/* pollset->po.mu lock must be held by the caller before calling this */ +static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_closure *closure) { + GPR_TIMER_BEGIN("pollset_shutdown", 0); + GPR_ASSERT(!pollset->shutting_down); + pollset->shutting_down = true; + pollset->shutdown_done = closure; + pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); + + /* If the pollset has any workers, we cannot call finish_shutdown_locked() + because it would release the underlying polling island. In such a case, we + let the last worker call finish_shutdown_locked() from pollset_work() */ + if (!pollset_has_workers(pollset)) { + GPR_ASSERT(!pollset->finish_shutdown_called); + GPR_TIMER_MARK("pollset_shutdown.finish_shutdown_locked", 0); + finish_shutdown_locked(exec_ctx, pollset); + } + GPR_TIMER_END("pollset_shutdown", 0); +} + +/* pollset_shutdown is guaranteed to be called before pollset_destroy. So other + * than destroying the mutexes, there is nothing special that needs to be done + * here */ +static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { + GPR_ASSERT(!pollset_has_workers(pollset)); + gpr_mu_destroy(&pollset->po.mu); +} + +static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx, + polling_island *pi) { + if (gpr_mu_trylock(&pi->workqueue_read_mu)) { + gpr_mpscq_node *n = gpr_mpscq_pop(&pi->workqueue_items); + gpr_mu_unlock(&pi->workqueue_read_mu); + if (n != NULL) { + if (gpr_atm_full_fetch_add(&pi->workqueue_item_count, -1) > 1) { + workqueue_maybe_wakeup(pi); + } + grpc_closure *c = (grpc_closure *)n; + grpc_error *error = c->error_data.error; +#ifndef NDEBUG + c->scheduled = false; +#endif + c->cb(exec_ctx, c->cb_arg, error); + GRPC_ERROR_UNREF(error); + return true; + } else if (gpr_atm_no_barrier_load(&pi->workqueue_item_count) > 0) { + /* n == NULL might mean there's work but it's not available to be popped + * yet - try to ensure another workqueue wakes up to check shortly if so + */ + workqueue_maybe_wakeup(pi); + } + } + return false; +} + +/* NOTE: This function may modify 'now' */ +static bool acquire_polling_lease(grpc_pollset_worker *worker, + polling_island *pi, gpr_timespec deadline, + gpr_timespec *now) { + bool is_lease_acquired = false; + + gpr_mu_lock(&pi->worker_list_mu); // LOCK + long num_pollers = gpr_atm_no_barrier_load(&pi->poller_count); + + if (num_pollers >= g_max_pollers_per_pi) { + push_back_worker_node(&pi->worker_list_head, &worker->pi_list_link); + gpr_mu_unlock(&pi->worker_list_mu); // UNLOCK + + bool is_timeout = false; + int ret; + int timeout_ms = poll_deadline_to_millis_timeout(deadline, *now); + if (timeout_ms == -1) { + ret = sigwaitinfo(&g_wakeup_sig_set, NULL); + } else { + struct timespec sigwait_timeout = millis_to_timespec(timeout_ms); + GRPC_SCHEDULING_START_BLOCKING_REGION; + ret = sigtimedwait(&g_wakeup_sig_set, NULL, &sigwait_timeout); + GRPC_SCHEDULING_END_BLOCKING_REGION; + } + + if (ret == -1) { + if (errno == EAGAIN) { + is_timeout = true; + } else { + /* NOTE: This should not happen. If we see these log messages, it means + we are most likely doing something incorrect in the setup * needed + for sigwaitinfo/sigtimedwait */ + gpr_log(GPR_ERROR, + "sigtimedwait failed with retcode: %d (timeout_ms: %d)", errno, + timeout_ms); + } + } + + /* Did the worker come out of sigtimedwait due to a thread that just + exited epoll and kicking it (in release_polling_lease function). */ + bool is_polling_turn = gpr_atm_acq_load(&worker->is_polling_turn); + + /* Did the worker come out of sigtimedwait due to a thread alerting it that + some completion event was (likely) available in the completion queue */ + bool is_kicked = gpr_atm_no_barrier_load(&worker->is_kicked); + + if (is_kicked || is_timeout) { + *now = deadline; /* Essentially make the epoll timeout = 0 */ + } else if (is_polling_turn) { + *now = gpr_now(GPR_CLOCK_MONOTONIC); /* Reduce the epoll timeout */ + } + + gpr_mu_lock(&pi->worker_list_mu); // LOCK + /* The node might have already been removed from the list by the poller + that kicked this. However it is safe to call 'remove_worker_node' on + an already detached node */ + remove_worker_node(&worker->pi_list_link); + /* It is important to read the num_pollers again under the lock so that we + * have the latest num_pollers value that doesn't change while we are doing + * the "(num_pollers < g_max_pollers_per_pi)" a a few lines below */ + num_pollers = gpr_atm_no_barrier_load(&pi->poller_count); + } + + if (num_pollers < g_max_pollers_per_pi) { + gpr_atm_no_barrier_fetch_add(&pi->poller_count, 1); + is_lease_acquired = true; + } + + gpr_mu_unlock(&pi->worker_list_mu); // UNLOCK + return is_lease_acquired; +} + +static void release_polling_lease(polling_island *pi, grpc_error **error) { + gpr_mu_lock(&pi->worker_list_mu); + + gpr_atm_no_barrier_fetch_add(&pi->poller_count, -1); + worker_node *node = pop_front_worker_node(&pi->worker_list_head); + if (node != NULL) { + grpc_pollset_worker *next_worker = WORKER_FROM_WORKER_LIST_NODE(node); + append_error(error, poller_kick(next_worker), "poller kick error"); + } + + gpr_mu_unlock(&pi->worker_list_mu); +} + +#define GRPC_EPOLL_MAX_EVENTS 100 +static void pollset_do_epoll_pwait(grpc_exec_ctx *exec_ctx, int epoll_fd, + grpc_pollset *pollset, polling_island *pi, + grpc_pollset_worker *worker, + gpr_timespec now, gpr_timespec deadline, + sigset_t *sig_mask, grpc_error **error) { + /* Only g_max_pollers_per_pi threads can be doing polling in parallel. + If we cannot get a lease, we cannot continue to do epoll_pwait() */ + if (!acquire_polling_lease(worker, pi, deadline, &now)) { + return; + } + + struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS]; + int ep_rv; + char *err_msg; + const char *err_desc = "pollset_work_and_unlock"; + + /* timeout_ms is the time between 'now' and 'deadline' */ + int timeout_ms = poll_deadline_to_millis_timeout(deadline, now); + + GRPC_SCHEDULING_START_BLOCKING_REGION; + ep_rv = + epoll_pwait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms, sig_mask); + GRPC_SCHEDULING_END_BLOCKING_REGION; + + /* Give back the lease right away so that some other thread can enter */ + release_polling_lease(pi, error); + + if (ep_rv < 0) { + if (errno != EINTR) { + gpr_asprintf(&err_msg, + "epoll_wait() epoll fd: %d failed with error: %d (%s)", + epoll_fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + } else { + /* We were interrupted. Save an interation by doing a zero timeout + epoll_wait to see if there are any other events of interest */ + GRPC_POLLING_TRACE("pollset_work: pollset: %p, worker: %p received kick", + (void *)pollset, (void *)worker); + ep_rv = epoll_wait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, 0); + } + } + +#ifdef GRPC_TSAN + /* See the definition of g_poll_sync for more details */ + gpr_atm_acq_load(&g_epoll_sync); +#endif /* defined(GRPC_TSAN) */ + + for (int i = 0; i < ep_rv; ++i) { + void *data_ptr = ep_ev[i].data.ptr; + if (data_ptr == &pi->workqueue_wakeup_fd) { + append_error(error, + grpc_wakeup_fd_consume_wakeup(&pi->workqueue_wakeup_fd), + err_desc); + maybe_do_workqueue_work(exec_ctx, pi); + } else if (data_ptr == &polling_island_wakeup_fd) { + GRPC_POLLING_TRACE( + "pollset_work: pollset: %p, worker: %p polling island (epoll_fd: " + "%d) got merged", + (void *)pollset, (void *)worker, epoll_fd); + /* This means that our polling island is merged with a different + island. We do not have to do anything here since the subsequent call + to the function pollset_work_and_unlock() will pick up the correct + epoll_fd */ + } else { + grpc_fd *fd = data_ptr; + int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP); + int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI); + int write_ev = ep_ev[i].events & EPOLLOUT; + if (read_ev || cancel) { + fd_become_readable(exec_ctx, fd, pollset); + } + if (write_ev || cancel) { + fd_become_writable(exec_ctx, fd); + } + } + } +} + +/* Note: sig_mask contains the signal mask to use *during* epoll_wait() */ +static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset, + grpc_pollset_worker *worker, + gpr_timespec now, gpr_timespec deadline, + sigset_t *sig_mask, grpc_error **error) { + int epoll_fd = -1; + polling_island *pi = NULL; + GPR_TIMER_BEGIN("pollset_work_and_unlock", 0); + + /* We need to get the epoll_fd to wait on. The epoll_fd is in inside the + latest polling island pointed by pollset->po.pi + + Since epoll_fd is immutable, it is safe to read it without a lock on the + polling island. There is however a possibility that the polling island from + which we got the epoll_fd, got merged with another island in the meantime. + This is okay because in such a case, we will wakeup right-away from + epoll_pwait() (because any merge will poison the old polling island's epoll + set 'polling_island_wakeup_fd') and then pick up the latest polling_island + the next time this function - pollset_work_and_unlock()) is called */ + + if (pollset->po.pi == NULL) { + pollset->po.pi = polling_island_create(exec_ctx, NULL, error); + if (pollset->po.pi == NULL) { + GPR_TIMER_END("pollset_work_and_unlock", 0); + return; /* Fatal error. Cannot continue */ + } + + PI_ADD_REF(pollset->po.pi, "ps"); + GRPC_POLLING_TRACE("pollset_work: pollset: %p created new pi: %p", + (void *)pollset, (void *)pollset->po.pi); + } + + pi = polling_island_maybe_get_latest(pollset->po.pi); + epoll_fd = pi->epoll_fd; + + /* Update the pollset->po.pi since the island being pointed by + pollset->po.pi maybe older than the one pointed by pi) */ + if (pollset->po.pi != pi) { + /* Always do PI_ADD_REF before PI_UNREF because PI_UNREF may cause the + polling island to be deleted */ + PI_ADD_REF(pi, "ps"); + PI_UNREF(exec_ctx, pollset->po.pi, "ps"); + pollset->po.pi = pi; + } + + /* Add an extra ref so that the island does not get destroyed (which means + the epoll_fd won't be closed) while we are are doing an epoll_wait() on the + epoll_fd */ + PI_ADD_REF(pi, "ps_work"); + gpr_mu_unlock(&pollset->po.mu); + + /* If we get some workqueue work to do, it might end up completing an item on + the completion queue, so there's no need to poll... so we skip that and + redo the complete loop to verify */ + if (!maybe_do_workqueue_work(exec_ctx, pi)) { + g_current_thread_polling_island = pi; + pollset_do_epoll_pwait(exec_ctx, epoll_fd, pollset, pi, worker, now, + deadline, sig_mask, error); + g_current_thread_polling_island = NULL; + } + + GPR_ASSERT(pi != NULL); + + /* Before leaving, release the extra ref we added to the polling island. It + is important to use "pi" here (i.e our old copy of pollset->po.pi + that we got before releasing the polling island lock). This is because + pollset->po.pi pointer might get udpated in other parts of the + code when there is an island merge while we are doing epoll_wait() above */ + PI_UNREF(exec_ctx, pi, "ps_work"); + + GPR_TIMER_END("pollset_work_and_unlock", 0); +} + +/* pollset->po.mu lock must be held by the caller before calling this. + The function pollset_work() may temporarily release the lock (pollset->po.mu) + during the course of its execution but it will always re-acquire the lock and + ensure that it is held by the time the function returns */ +static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_pollset_worker **worker_hdl, + gpr_timespec now, gpr_timespec deadline) { + GPR_TIMER_BEGIN("pollset_work", 0); + grpc_error *error = GRPC_ERROR_NONE; + + grpc_pollset_worker worker; + pollset_worker_init(&worker); + + if (worker_hdl) *worker_hdl = &worker; + + gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); + gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); + + if (pollset->kicked_without_pollers) { + /* If the pollset was kicked without pollers, pretend that the current + worker got the kick and skip polling. A kick indicates that there is some + work that needs attention like an event on the completion queue or an + alarm */ + GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0); + pollset->kicked_without_pollers = 0; + } else if (!pollset->shutting_down) { + /* We use the posix-signal with number 'grpc_wakeup_signal' for waking up + (i.e 'kicking') a worker in the pollset. A 'kick' is a way to inform the + worker that there is some pending work that needs immediate attention + (like an event on the completion queue, or a polling island merge that + results in a new epoll-fd to wait on) and that the worker should not + spend time waiting in epoll_pwait(). + + A worker can be kicked anytime from the point it is added to the pollset + via push_front_worker() (or push_back_worker()) to the point it is + removed via remove_worker(). + If the worker is kicked before/during it calls epoll_pwait(), it should + immediately exit from epoll_wait(). If the worker is kicked after it + returns from epoll_wait(), then nothing really needs to be done. + + To accomplish this, we mask 'grpc_wakeup_signal' on this thread at all + times *except* when it is in epoll_pwait(). This way, the worker never + misses acting on a kick */ + + if (!g_initialized_sigmask) { + sigemptyset(&g_wakeup_sig_set); + sigaddset(&g_wakeup_sig_set, grpc_wakeup_signal); + pthread_sigmask(SIG_BLOCK, &g_wakeup_sig_set, &g_orig_sigmask); + sigdelset(&g_orig_sigmask, grpc_wakeup_signal); + g_initialized_sigmask = true; + /* new_mask: The new thread mask which blocks 'grpc_wakeup_signal'. + This is the mask used at all times *except during + epoll_wait()*" + g_orig_sigmask: The thread mask which allows 'grpc_wakeup_signal' and + this is the mask to use *during epoll_wait()* + + The new_mask is set on the worker before it is added to the pollset + (i.e before it can be kicked) */ + } + + push_front_worker(pollset, &worker); /* Add worker to pollset */ + + pollset_work_and_unlock(exec_ctx, pollset, &worker, now, deadline, + &g_orig_sigmask, &error); + grpc_exec_ctx_flush(exec_ctx); + + gpr_mu_lock(&pollset->po.mu); + + /* Note: There is no need to reset worker.is_kicked to 0 since we are no + longer going to use this worker */ + remove_worker(pollset, &worker); + } + + /* If we are the last worker on the pollset (i.e pollset_has_workers() is + false at this point) and the pollset is shutting down, we may have to + finish the shutdown process by calling finish_shutdown_locked(). + See pollset_shutdown() for more details. + + Note: Continuing to access pollset here is safe; it is the caller's + responsibility to not destroy a pollset when it has outstanding calls to + pollset_work() */ + if (pollset->shutting_down && !pollset_has_workers(pollset) && + !pollset->finish_shutdown_called) { + GPR_TIMER_MARK("pollset_work.finish_shutdown_locked", 0); + finish_shutdown_locked(exec_ctx, pollset); + + gpr_mu_unlock(&pollset->po.mu); + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(&pollset->po.mu); + } + + if (worker_hdl) *worker_hdl = NULL; + + gpr_tls_set(&g_current_thread_pollset, (intptr_t)0); + gpr_tls_set(&g_current_thread_worker, (intptr_t)0); + + GPR_TIMER_END("pollset_work", 0); + + GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); + return error; +} + +static void add_poll_object(grpc_exec_ctx *exec_ctx, poll_obj *bag, + poll_obj_type bag_type, poll_obj *item, + poll_obj_type item_type) { + GPR_TIMER_BEGIN("add_poll_object", 0); + +#ifdef PO_DEBUG + GPR_ASSERT(item->obj_type == item_type); + GPR_ASSERT(bag->obj_type == bag_type); +#endif + + grpc_error *error = GRPC_ERROR_NONE; + polling_island *pi_new = NULL; + + gpr_mu_lock(&bag->mu); + gpr_mu_lock(&item->mu); + +retry: + /* + * 1) If item->pi and bag->pi are both non-NULL and equal, do nothing + * 2) If item->pi and bag->pi are both NULL, create a new polling island (with + * a refcount of 2) and point item->pi and bag->pi to the new island + * 3) If exactly one of item->pi or bag->pi is NULL, update it to point to + * the other's non-NULL pi + * 4) Finally if item->pi and bag-pi are non-NULL and not-equal, merge the + * polling islands and update item->pi and bag->pi to point to the new + * island + */ + + /* Early out if we are trying to add an 'fd' to a 'bag' but the fd is already + * orphaned */ + if (item_type == POLL_OBJ_FD && (FD_FROM_PO(item))->orphaned) { + gpr_mu_unlock(&item->mu); + gpr_mu_unlock(&bag->mu); + return; + } + + if (item->pi == bag->pi) { + pi_new = item->pi; + if (pi_new == NULL) { + /* GPR_ASSERT(item->pi == bag->pi == NULL) */ + + /* If we are adding an fd to a bag (i.e pollset or pollset_set), then + * we need to do some extra work to make TSAN happy */ + if (item_type == POLL_OBJ_FD) { + /* Unlock before creating a new polling island: the polling island will + create a workqueue which creates a file descriptor, and holding an fd + lock here can eventually cause a loop to appear to TSAN (making it + unhappy). We don't think it's a real loop (there's an epoch point + where that loop possibility disappears), but the advantages of + keeping TSAN happy outweigh any performance advantage we might have + by keeping the lock held. */ + gpr_mu_unlock(&item->mu); + pi_new = polling_island_create(exec_ctx, FD_FROM_PO(item), &error); + gpr_mu_lock(&item->mu); + + /* Need to reverify any assumptions made between the initial lock and + getting to this branch: if they've changed, we need to throw away our + work and figure things out again. */ + if (item->pi != NULL) { + GRPC_POLLING_TRACE( + "add_poll_object: Raced creating new polling island. pi_new: %p " + "(fd: %d, %s: %p)", + (void *)pi_new, FD_FROM_PO(item)->fd, poll_obj_string(bag_type), + (void *)bag); + /* No need to lock 'pi_new' here since this is a new polling island + and no one has a reference to it yet */ + polling_island_remove_all_fds_locked(pi_new, true, &error); + + /* Ref and unref so that the polling island gets deleted during unref + */ + PI_ADD_REF(pi_new, "dance_of_destruction"); + PI_UNREF(exec_ctx, pi_new, "dance_of_destruction"); + goto retry; + } + } else { + pi_new = polling_island_create(exec_ctx, NULL, &error); + } + + GRPC_POLLING_TRACE( + "add_poll_object: Created new polling island. pi_new: %p (%s: %p, " + "%s: %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); + } else { + GRPC_POLLING_TRACE( + "add_poll_object: Same polling island. pi: %p (%s, %s)", + (void *)pi_new, poll_obj_string(item_type), + poll_obj_string(bag_type)); + } + } else if (item->pi == NULL) { + /* GPR_ASSERT(bag->pi != NULL) */ + /* Make pi_new point to latest pi*/ + pi_new = polling_island_lock(bag->pi); + + if (item_type == POLL_OBJ_FD) { + grpc_fd *fd = FD_FROM_PO(item); + polling_island_add_fds_locked(pi_new, &fd, 1, true, &error); + } + + gpr_mu_unlock(&pi_new->mu); + GRPC_POLLING_TRACE( + "add_poll_obj: item->pi was NULL. pi_new: %p (item(%s): %p, " + "bag(%s): %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); + } else if (bag->pi == NULL) { + /* GPR_ASSERT(item->pi != NULL) */ + /* Make pi_new to point to latest pi */ + pi_new = polling_island_lock(item->pi); + gpr_mu_unlock(&pi_new->mu); + GRPC_POLLING_TRACE( + "add_poll_obj: bag->pi was NULL. pi_new: %p (item(%s): %p, " + "bag(%s): %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); + } else { + pi_new = polling_island_merge(item->pi, bag->pi, &error); + GRPC_POLLING_TRACE( + "add_poll_obj: polling islands merged. pi_new: %p (item(%s): %p, " + "bag(%s): %p)", + (void *)pi_new, poll_obj_string(item_type), (void *)item, + poll_obj_string(bag_type), (void *)bag); + } + + /* At this point, pi_new is the polling island that both item->pi and bag->pi + MUST be pointing to */ + + if (item->pi != pi_new) { + PI_ADD_REF(pi_new, poll_obj_string(item_type)); + if (item->pi != NULL) { + PI_UNREF(exec_ctx, item->pi, poll_obj_string(item_type)); + } + item->pi = pi_new; + } + + if (bag->pi != pi_new) { + PI_ADD_REF(pi_new, poll_obj_string(bag_type)); + if (bag->pi != NULL) { + PI_UNREF(exec_ctx, bag->pi, poll_obj_string(bag_type)); + } + bag->pi = pi_new; + } + + gpr_mu_unlock(&item->mu); + gpr_mu_unlock(&bag->mu); + + GRPC_LOG_IF_ERROR("add_poll_object", error); + GPR_TIMER_END("add_poll_object", 0); +} + +static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_fd *fd) { + add_poll_object(exec_ctx, &pollset->po, POLL_OBJ_POLLSET, &fd->po, + POLL_OBJ_FD); +} + +/******************************************************************************* + * Pollset-set Definitions + */ + +static grpc_pollset_set *pollset_set_create(void) { + grpc_pollset_set *pss = gpr_malloc(sizeof(*pss)); + gpr_mu_init(&pss->po.mu); + pss->po.pi = NULL; +#ifdef PO_DEBUG + pss->po.obj_type = POLL_OBJ_POLLSET_SET; +#endif + return pss; +} + +static void pollset_set_destroy(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss) { + gpr_mu_destroy(&pss->po.mu); + + if (pss->po.pi != NULL) { + PI_UNREF(exec_ctx, pss->po.pi, "pss_destroy"); + } + + gpr_free(pss); +} + +static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + add_poll_object(exec_ctx, &pss->po, POLL_OBJ_POLLSET_SET, &fd->po, + POLL_OBJ_FD); +} + +static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + /* Nothing to do */ +} + +static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) { + add_poll_object(exec_ctx, &pss->po, POLL_OBJ_POLLSET_SET, &ps->po, + POLL_OBJ_POLLSET); +} + +static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) { + /* Nothing to do */ +} + +static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) { + add_poll_object(exec_ctx, &bag->po, POLL_OBJ_POLLSET_SET, &item->po, + POLL_OBJ_POLLSET_SET); +} + +static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) { + /* Nothing to do */ +} + +/******************************************************************************* + * Event engine binding + */ + +static void shutdown_engine(void) { + fd_global_shutdown(); + pollset_global_shutdown(); + polling_island_global_shutdown(); +} + +static const grpc_event_engine_vtable vtable = { + .pollset_size = sizeof(grpc_pollset), + + .fd_create = fd_create, + .fd_wrapped_fd = fd_wrapped_fd, + .fd_orphan = fd_orphan, + .fd_shutdown = fd_shutdown, + .fd_is_shutdown = fd_is_shutdown, + .fd_notify_on_read = fd_notify_on_read, + .fd_notify_on_write = fd_notify_on_write, + .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, + + .pollset_init = pollset_init, + .pollset_shutdown = pollset_shutdown, + .pollset_destroy = pollset_destroy, + .pollset_work = pollset_work, + .pollset_kick = pollset_kick, + .pollset_add_fd = pollset_add_fd, + + .pollset_set_create = pollset_set_create, + .pollset_set_destroy = pollset_set_destroy, + .pollset_set_add_pollset = pollset_set_add_pollset, + .pollset_set_del_pollset = pollset_set_del_pollset, + .pollset_set_add_pollset_set = pollset_set_add_pollset_set, + .pollset_set_del_pollset_set = pollset_set_del_pollset_set, + .pollset_set_add_fd = pollset_set_add_fd, + .pollset_set_del_fd = pollset_set_del_fd, + + .workqueue_ref = workqueue_ref, + .workqueue_unref = workqueue_unref, + .workqueue_scheduler = workqueue_scheduler, + + .shutdown_engine = shutdown_engine, +}; + +/* It is possible that GLIBC has epoll but the underlying kernel doesn't. + * Create a dummy epoll_fd to make sure epoll support is available */ +static bool is_epoll_available() { + int fd = epoll_create1(EPOLL_CLOEXEC); + if (fd < 0) { + gpr_log( + GPR_ERROR, + "epoll_create1 failed with error: %d. Not using epoll polling engine", + fd); + return false; + } + close(fd); + return true; +} + +/* This is mainly for testing purposes. Checks to see if environment variable + * GRPC_MAX_POLLERS_PER_PI is set and if so, assigns that value to + * g_max_pollers_per_pi (any negative value is considered INT_MAX) */ +static void set_max_pollers_per_island() { + char *s = gpr_getenv("GRPC_MAX_POLLERS_PER_PI"); + if (s) { + g_max_pollers_per_pi = (int)strtol(s, NULL, 10); + if (g_max_pollers_per_pi < 0) { + g_max_pollers_per_pi = INT_MAX; + } + } else { + g_max_pollers_per_pi = INT_MAX; + } + + gpr_log(GPR_INFO, "Max number of pollers per polling island: %d", + g_max_pollers_per_pi); +} + +const grpc_event_engine_vtable *grpc_init_epoll_limited_pollers_linux( + bool explicitly_requested) { + if (!explicitly_requested) { + return NULL; + } + + /* If use of signals is disabled, we cannot use epoll engine*/ + if (is_grpc_wakeup_signal_initialized && grpc_wakeup_signal < 0) { + return NULL; + } + + if (!grpc_has_wakeup_fd()) { + return NULL; + } + + if (!is_epoll_available()) { + return NULL; + } + + if (!is_grpc_wakeup_signal_initialized) { + grpc_use_signal(SIGRTMIN + 6); + } + + set_max_pollers_per_island(); + + fd_global_init(); + + if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { + return NULL; + } + + if (!GRPC_LOG_IF_ERROR("polling_island_global_init", + polling_island_global_init())) { + return NULL; + } + + return &vtable; +} + +#else /* defined(GRPC_LINUX_EPOLL) */ +#if defined(GRPC_POSIX_SOCKET) +#include "src/core/lib/iomgr/ev_posix.h" +/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return + * NULL */ +const grpc_event_engine_vtable *grpc_init_epoll_limited_pollers_linux( + bool explicitly_requested) { + return NULL; +} +#endif /* defined(GRPC_POSIX_SOCKET) */ +#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..379e1ded3b8b575173cf5e8503259ec0661cf14e --- /dev/null +++ b/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL_LIMITED_POLLERS_LINUX_H +#define GRPC_CORE_LIB_IOMGR_EV_EPOLL_LIMITED_POLLERS_LINUX_H + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/port.h" + +const grpc_event_engine_vtable *grpc_init_epoll_limited_pollers_linux( + bool explicitly_requested); + +#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL_LIMITED_POLLERS_LINUX_H */ diff --git a/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..bb44321922a18d7dd142962c3850f1b09e5731a0 --- /dev/null +++ b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c @@ -0,0 +1,1337 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +/* This polling engine is only relevant on linux kernels supporting epoll() */ +#ifdef GRPC_LINUX_EPOLL + +#include "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h" + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <poll.h> +#include <pthread.h> +#include <string.h> +#include <sys/epoll.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/cpu.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/thd.h> +#include <grpc/support/tls.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/lockfree_event.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/iomgr/workqueue.h" +#include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/block_annotate.h" + +/* TODO: sreek - Move this to init.c and initialize this like other tracers. */ +#define GRPC_POLLING_TRACE(fmt, ...) \ + if (GRPC_TRACER_ON(grpc_polling_trace)) { \ + gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \ + } + +/* The alarm system needs to be able to wakeup 'some poller' sometimes + * (specifically when a new alarm needs to be triggered earlier than the next + * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a + * case occurs. */ + +struct epoll_set; + +#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) + +/******************************************************************************* + * Fd Declarations + */ +struct grpc_fd { + gpr_mu mu; + struct epoll_set *eps; + + int fd; + + /* The fd is either closed or we relinquished control of it. In either cases, + this indicates that the 'fd' on this structure is no longer valid */ + bool orphaned; + + gpr_atm read_closure; + gpr_atm write_closure; + + struct grpc_fd *freelist_next; + grpc_closure *on_done_closure; + + grpc_iomgr_object iomgr_object; +}; + +static void fd_global_init(void); +static void fd_global_shutdown(void); + +/******************************************************************************* + * epoll set Declarations + */ + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG + +#define EPS_ADD_REF(p, r) eps_add_ref_dbg((p), (r), __FILE__, __LINE__) +#define EPS_UNREF(exec_ctx, p, r) \ + eps_unref_dbg((exec_ctx), (p), (r), __FILE__, __LINE__) + +#else /* defined(GRPC_WORKQUEUE_REFCOUNT_DEBUG) */ + +#define EPS_ADD_REF(p, r) eps_add_ref((p)) +#define EPS_UNREF(exec_ctx, p, r) eps_unref((exec_ctx), (p)) + +#endif /* !defined(GRPC_EPS_REF_COUNT_DEBUG) */ + +/* This is also used as grpc_workqueue (by directly casting it) */ +typedef struct epoll_set { + grpc_closure_scheduler workqueue_scheduler; + + /* Mutex poller should acquire to poll this. This enforces that only one + * poller can be polling on epoll_set at any time */ + gpr_mu mu; + + /* Ref count. Use EPS_ADD_REF() and EPS_UNREF() macros to increment/decrement + the refcount. Once the ref count becomes zero, this structure is destroyed + which means we should ensure that there is never a scenario where a + EPS_ADD_REF() is racing with a EPS_UNREF() that just made the ref_count + zero. */ + gpr_atm ref_count; + + /* Number of threads currently polling on this epoll set*/ + gpr_atm poller_count; + /* Mutex guarding the read end of the workqueue (must be held to pop from + * workqueue_items) */ + gpr_mu workqueue_read_mu; + /* Queue of closures to be executed */ + gpr_mpscq workqueue_items; + /* Count of items in workqueue_items */ + gpr_atm workqueue_item_count; + /* Wakeup fd used to wake pollers to check the contents of workqueue_items */ + grpc_wakeup_fd workqueue_wakeup_fd; + + /* Is the epoll set shutdown */ + gpr_atm is_shutdown; + + /* The fd of the underlying epoll set */ + int epoll_fd; +} epoll_set; + +/******************************************************************************* + * Pollset Declarations + */ +struct grpc_pollset_worker { + gpr_cv kick_cv; + + struct grpc_pollset_worker *next; + struct grpc_pollset_worker *prev; +}; + +struct grpc_pollset { + gpr_mu mu; + struct epoll_set *eps; + + grpc_pollset_worker root_worker; + bool kicked_without_pollers; + + bool shutting_down; /* Is the pollset shutting down ? */ + bool finish_shutdown_called; /* Is the 'finish_shutdown_locked()' called ? */ + grpc_closure *shutdown_done; /* Called after after shutdown is complete */ +}; + +/******************************************************************************* + * Pollset-set Declarations + */ +struct grpc_pollset_set {}; + +/***************************************************************************** + * Dedicated polling threads and pollsets - Declarations + */ + +size_t g_num_eps = 1; +struct epoll_set **g_epoll_sets = NULL; +gpr_atm g_next_eps; +size_t g_num_threads_per_eps = 1; +gpr_thd_id *g_poller_threads = NULL; + +/* Used as read-notifier pollsets for fds. We won't be using read notifier + * pollsets with this polling engine. So it does not matter what pollset we + * return */ +grpc_pollset g_read_notifier; + +static void add_fd_to_eps(grpc_fd *fd); +static bool init_epoll_sets(); +static void shutdown_epoll_sets(); +static void poller_thread_loop(void *arg); +static void start_poller_threads(); +static void shutdown_poller_threads(); + +/******************************************************************************* + * Common helpers + */ + +static bool append_error(grpc_error **composite, grpc_error *error, + const char *desc) { + if (error == GRPC_ERROR_NONE) return true; + if (*composite == GRPC_ERROR_NONE) { + *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); + } + *composite = grpc_error_add_child(*composite, error); + return false; +} + +/******************************************************************************* + * epoll set Definitions + */ + +/* The wakeup fd that is used to wake up all threads in an epoll_set informing + that the epoll set is shutdown. This wakeup fd initialized to be readable + and MUST NOT be consumed i.e the threads that woke up MUST NOT call + grpc_wakeup_fd_consume_wakeup() */ +static grpc_wakeup_fd epoll_set_wakeup_fd; + +/* The epoll set being polled right now. + See comments in workqueue_maybe_wakeup for why this is tracked. */ +static __thread epoll_set *g_current_thread_epoll_set; + +/* Forward declaration */ +static void epoll_set_delete(epoll_set *eps); +static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error); + +#ifdef GRPC_TSAN +/* Currently TSAN may incorrectly flag data races between epoll_ctl and + epoll_wait for any grpc_fd structs that are added to the epoll set via + epoll_ctl and are returned (within a very short window) via epoll_wait(). + + To work-around this race, we establish a happens-before relation between + the code just-before epoll_ctl() and the code after epoll_wait() by using + this atomic */ +gpr_atm g_epoll_sync; +#endif /* defined(GRPC_TSAN) */ + +static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = { + workqueue_enqueue, workqueue_enqueue, "workqueue"}; + +static void eps_add_ref(epoll_set *eps); +static void eps_unref(grpc_exec_ctx *exec_ctx, epoll_set *eps); + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG +static void eps_add_ref_dbg(epoll_set *eps, const char *reason, + const char *file, int line) { + long old_cnt = gpr_atm_acq_load(&eps->ref_count); + eps_add_ref(eps); + gpr_log(GPR_DEBUG, "Add ref eps: %p, old: %ld -> new:%ld (%s) - (%s, %d)", + (void *)eps, old_cnt, old_cnt + 1, reason, file, line); +} + +static void eps_unref_dbg(grpc_exec_ctx *exec_ctx, epoll_set *eps, + const char *reason, const char *file, int line) { + long old_cnt = gpr_atm_acq_load(&eps->ref_count); + eps_unref(exec_ctx, eps); + gpr_log(GPR_DEBUG, "Unref eps: %p, old:%ld -> new:%ld (%s) - (%s, %d)", + (void *)eps, old_cnt, (old_cnt - 1), reason, file, line); +} + +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue, + const char *file, int line, + const char *reason) { + if (workqueue != NULL) { + eps_add_ref_dbg((epoll_set *)workqueue, reason, file, line); + } + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, + const char *file, int line, const char *reason) { + if (workqueue != NULL) { + eps_unref_dbg(exec_ctx, (epoll_set *)workqueue, reason, file, line); + } +} +#else +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) { + if (workqueue != NULL) { + eps_add_ref((epoll_set *)workqueue); + } + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, + grpc_workqueue *workqueue) { + if (workqueue != NULL) { + eps_unref(exec_ctx, (epoll_set *)workqueue); + } +} +#endif + +static void eps_add_ref(epoll_set *eps) { + gpr_atm_no_barrier_fetch_add(&eps->ref_count, 1); +} + +static void eps_unref(grpc_exec_ctx *exec_ctx, epoll_set *eps) { + /* If ref count went to zero, delete the epoll set. This deletion is + not done under a lock since once the ref count goes to zero, we are + guaranteed that no one else holds a reference to the epoll set (and + that there is no racing eps_add_ref() call either).*/ + if (1 == gpr_atm_full_fetch_add(&eps->ref_count, -1)) { + epoll_set_delete(eps); + } +} + +static void epoll_set_add_fd_locked(epoll_set *eps, grpc_fd *fd, + grpc_error **error) { + int err; + struct epoll_event ev; + char *err_msg; + const char *err_desc = "epoll_set_add_fd_locked"; + +#ifdef GRPC_TSAN + /* See the definition of g_epoll_sync for more context */ + gpr_atm_rel_store(&g_epoll_sync, (gpr_atm)0); +#endif /* defined(GRPC_TSAN) */ + + ev.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET); + ev.data.ptr = fd; + err = epoll_ctl(eps->epoll_fd, EPOLL_CTL_ADD, fd->fd, &ev); + if (err < 0 && errno != EEXIST) { + gpr_asprintf( + &err_msg, + "epoll_ctl (epoll_fd: %d) add fd: %d failed with error: %d (%s)", + eps->epoll_fd, fd->fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } +} + +static void epoll_set_add_wakeup_fd_locked(epoll_set *eps, + grpc_wakeup_fd *wakeup_fd, + grpc_error **error) { + struct epoll_event ev; + int err; + char *err_msg; + const char *err_desc = "epoll_set_add_wakeup_fd"; + + ev.events = (uint32_t)(EPOLLIN | EPOLLET); + ev.data.ptr = wakeup_fd; + err = epoll_ctl(eps->epoll_fd, EPOLL_CTL_ADD, + GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), &ev); + if (err < 0 && errno != EEXIST) { + gpr_asprintf(&err_msg, + "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with " + "error: %d (%s)", + eps->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), errno, + strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } +} + +static void epoll_set_remove_fd(epoll_set *eps, grpc_fd *fd, bool is_fd_closed, + grpc_error **error) { + int err; + char *err_msg; + const char *err_desc = "epoll_set_remove_fd"; + + /* If fd is already closed, then it would have been automatically been removed + from the epoll set */ + if (!is_fd_closed) { + err = epoll_ctl(eps->epoll_fd, EPOLL_CTL_DEL, fd->fd, NULL); + if (err < 0 && errno != ENOENT) { + gpr_asprintf( + &err_msg, + "epoll_ctl (epoll_fd: %d) del fd: %d failed with error: %d (%s)", + eps->epoll_fd, fd->fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + gpr_free(err_msg); + } + } +} + +/* Might return NULL in case of an error */ +static epoll_set *epoll_set_create(grpc_error **error) { + epoll_set *eps = NULL; + const char *err_desc = "epoll_set_create"; + + *error = GRPC_ERROR_NONE; + + eps = gpr_malloc(sizeof(*eps)); + eps->workqueue_scheduler.vtable = &workqueue_scheduler_vtable; + eps->epoll_fd = -1; + + gpr_mu_init(&eps->mu); + gpr_mu_init(&eps->workqueue_read_mu); + gpr_mpscq_init(&eps->workqueue_items); + gpr_atm_rel_store(&eps->workqueue_item_count, 0); + + gpr_atm_rel_store(&eps->ref_count, 0); + gpr_atm_rel_store(&eps->poller_count, 0); + + gpr_atm_rel_store(&eps->is_shutdown, false); + + if (!append_error(error, grpc_wakeup_fd_init(&eps->workqueue_wakeup_fd), + err_desc)) { + goto done; + } + + eps->epoll_fd = epoll_create1(EPOLL_CLOEXEC); + + if (eps->epoll_fd < 0) { + append_error(error, GRPC_OS_ERROR(errno, "epoll_create1"), err_desc); + goto done; + } + + epoll_set_add_wakeup_fd_locked(eps, &eps->workqueue_wakeup_fd, error); + +done: + if (*error != GRPC_ERROR_NONE) { + epoll_set_delete(eps); + eps = NULL; + } + return eps; +} + +static void epoll_set_delete(epoll_set *eps) { + if (eps->epoll_fd >= 0) { + close(eps->epoll_fd); + } + + GPR_ASSERT(gpr_atm_no_barrier_load(&eps->workqueue_item_count) == 0); + gpr_mu_destroy(&eps->mu); + gpr_mu_destroy(&eps->workqueue_read_mu); + gpr_mpscq_destroy(&eps->workqueue_items); + grpc_wakeup_fd_destroy(&eps->workqueue_wakeup_fd); + + gpr_free(eps); +} + +static void workqueue_maybe_wakeup(epoll_set *eps) { + /* If this thread is the current poller, then it may be that it's about to + decrement the current poller count, so we need to look past this thread */ + bool is_current_poller = (g_current_thread_epoll_set == eps); + gpr_atm min_current_pollers_for_wakeup = is_current_poller ? 1 : 0; + gpr_atm current_pollers = gpr_atm_no_barrier_load(&eps->poller_count); + /* Only issue a wakeup if it's likely that some poller could come in and take + it right now. Note that since we do an anticipatory mpscq_pop every poll + loop, it's ok if we miss the wakeup here, as we'll get the work item when + the next poller enters anyway. */ + if (current_pollers > min_current_pollers_for_wakeup) { + GRPC_LOG_IF_ERROR("workqueue_wakeup_fd", + grpc_wakeup_fd_wakeup(&eps->workqueue_wakeup_fd)); + } +} + +static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error) { + GPR_TIMER_BEGIN("workqueue.enqueue", 0); + grpc_workqueue *workqueue = (grpc_workqueue *)closure->scheduler; + /* take a ref to the workqueue: otherwise it can happen that whatever events + * this kicks off ends up destroying the workqueue before this function + * completes */ + GRPC_WORKQUEUE_REF(workqueue, "enqueue"); + epoll_set *eps = (epoll_set *)workqueue; + gpr_atm last = gpr_atm_no_barrier_fetch_add(&eps->workqueue_item_count, 1); + closure->error_data.error = error; + gpr_mpscq_push(&eps->workqueue_items, &closure->next_data.atm_next); + if (last == 0) { + workqueue_maybe_wakeup(eps); + } + + GRPC_WORKQUEUE_UNREF(exec_ctx, workqueue, "enqueue"); + GPR_TIMER_END("workqueue.enqueue", 0); +} + +static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) { + epoll_set *eps = (epoll_set *)workqueue; + return workqueue == NULL ? grpc_schedule_on_exec_ctx + : &eps->workqueue_scheduler; +} + +static grpc_error *epoll_set_global_init() { + grpc_error *error = GRPC_ERROR_NONE; + + error = grpc_wakeup_fd_init(&epoll_set_wakeup_fd); + if (error == GRPC_ERROR_NONE) { + error = grpc_wakeup_fd_wakeup(&epoll_set_wakeup_fd); + } + + return error; +} + +static void epoll_set_global_shutdown() { + grpc_wakeup_fd_destroy(&epoll_set_wakeup_fd); +} + +/******************************************************************************* + * Fd Definitions + */ + +/* We need to keep a freelist not because of any concerns of malloc performance + * but instead so that implementations with multiple threads in (for example) + * epoll_wait deal with the race between pollset removal and incoming poll + * notifications. + * + * The problem is that the poller ultimately holds a reference to this + * object, so it is very difficult to know when is safe to free it, at least + * without some expensive synchronization. + * + * If we keep the object freelisted, in the worst case losing this race just + * becomes a spurious read notification on a reused fd. + */ + +static grpc_fd *fd_freelist = NULL; +static gpr_mu fd_freelist_mu; + +static grpc_fd *get_fd_from_freelist() { + grpc_fd *new_fd = NULL; + + gpr_mu_lock(&fd_freelist_mu); + if (fd_freelist != NULL) { + new_fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + } + gpr_mu_unlock(&fd_freelist_mu); + return new_fd; +} + +static void add_fd_to_freelist(grpc_fd *fd) { + gpr_mu_lock(&fd_freelist_mu); + fd->freelist_next = fd_freelist; + fd_freelist = fd; + grpc_iomgr_unregister_object(&fd->iomgr_object); + + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); + + gpr_mu_unlock(&fd_freelist_mu); +} + +static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } + +static void fd_global_shutdown(void) { + gpr_mu_lock(&fd_freelist_mu); + gpr_mu_unlock(&fd_freelist_mu); + while (fd_freelist != NULL) { + grpc_fd *fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + gpr_mu_destroy(&fd->mu); + gpr_free(fd); + } + gpr_mu_destroy(&fd_freelist_mu); +} + +static grpc_fd *fd_create(int fd, const char *name) { + grpc_fd *new_fd = get_fd_from_freelist(); + if (new_fd == NULL) { + new_fd = gpr_malloc(sizeof(grpc_fd)); + gpr_mu_init(&new_fd->mu); + } + + /* Note: It is not really needed to get the new_fd->mu lock here. If this + * is a newly created fd (or an fd we got from the freelist), no one else + * would be holding a lock to it anyway. */ + gpr_mu_lock(&new_fd->mu); + new_fd->eps = NULL; + + new_fd->fd = fd; + new_fd->orphaned = false; + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); + + new_fd->freelist_next = NULL; + new_fd->on_done_closure = NULL; + + gpr_mu_unlock(&new_fd->mu); + + char *fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); + gpr_free(fd_name); + + /* Associate the fd with one of the eps */ + add_fd_to_eps(new_fd); + return new_fd; +} + +static int fd_wrapped_fd(grpc_fd *fd) { + int ret_fd = -1; + gpr_mu_lock(&fd->mu); + if (!fd->orphaned) { + ret_fd = fd->fd; + } + gpr_mu_unlock(&fd->mu); + + return ret_fd; +} + +static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *on_done, int *release_fd, + const char *reason) { + bool is_fd_closed = false; + grpc_error *error = GRPC_ERROR_NONE; + epoll_set *unref_eps = NULL; + + gpr_mu_lock(&fd->mu); + fd->on_done_closure = on_done; + + /* If release_fd is not NULL, we should be relinquishing control of the file + descriptor fd->fd (but we still own the grpc_fd structure). */ + if (release_fd != NULL) { + *release_fd = fd->fd; + } else { + close(fd->fd); + is_fd_closed = true; + } + + fd->orphaned = true; + + /* Remove the fd from the epoll set */ + if (fd->eps != NULL) { + epoll_set_remove_fd(fd->eps, fd, is_fd_closed, &error); + unref_eps = fd->eps; + fd->eps = NULL; + } + + grpc_closure_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error)); + + gpr_mu_unlock(&fd->mu); + + /* We are done with this fd. Release it (i.e add back to freelist) */ + add_fd_to_freelist(fd); + + if (unref_eps != NULL) { + /* Unref stale epoll set here, outside the fd lock above. + The epoll set owns a workqueue which owns an fd, and unreffing + inside the lock can cause an eventual lock loop that makes TSAN very + unhappy. */ + EPS_UNREF(exec_ctx, unref_eps, "fd_orphan"); + } + GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error)); + GRPC_ERROR_UNREF(error); +} + +/* This polling engine doesn't really need the read notifier functionality. So + * it just returns a dummy read notifier pollset */ +static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, + grpc_fd *fd) { + return &g_read_notifier; +} + +static bool fd_is_shutdown(grpc_fd *fd) { + return grpc_lfev_is_shutdown(&fd->read_closure); +} + +/* Might be called multiple times */ +static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { + shutdown(fd->fd, SHUT_RDWR); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + } + GRPC_ERROR_UNREF(why); +} + +static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure); +} + +static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure); +} + +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { return NULL; } + +/******************************************************************************* + * Pollset Definitions + */ +/* TODO: sreek - Not needed anymore */ +GPR_TLS_DECL(g_current_thread_pollset); +GPR_TLS_DECL(g_current_thread_worker); + +static void pollset_worker_init(grpc_pollset_worker *worker) { + worker->next = worker->prev = NULL; + gpr_cv_init(&worker->kick_cv); +} + +/* Global state management */ +static grpc_error *pollset_global_init(void) { + gpr_tls_init(&g_current_thread_pollset); + gpr_tls_init(&g_current_thread_worker); + return GRPC_ERROR_NONE; +} + +static void pollset_global_shutdown(void) { + gpr_tls_destroy(&g_current_thread_pollset); + gpr_tls_destroy(&g_current_thread_worker); +} + +static grpc_error *pollset_worker_kick(grpc_pollset_worker *worker) { + gpr_cv_signal(&worker->kick_cv); + return GRPC_ERROR_NONE; +} + +/* Return 1 if the pollset has active threads in pollset_work (pollset must + * be locked) */ +static int pollset_has_workers(grpc_pollset *p) { + return p->root_worker.next != &p->root_worker; +} + +static void remove_worker(grpc_pollset *p, grpc_pollset_worker *worker) { + worker->prev->next = worker->next; + worker->next->prev = worker->prev; +} + +static grpc_pollset_worker *pop_front_worker(grpc_pollset *p) { + if (pollset_has_workers(p)) { + grpc_pollset_worker *w = p->root_worker.next; + remove_worker(p, w); + return w; + } else { + return NULL; + } +} + +static void push_back_worker(grpc_pollset *p, grpc_pollset_worker *worker) { + worker->next = &p->root_worker; + worker->prev = worker->next->prev; + worker->prev->next = worker->next->prev = worker; +} + +static void push_front_worker(grpc_pollset *p, grpc_pollset_worker *worker) { + worker->prev = &p->root_worker; + worker->next = worker->prev->next; + worker->prev->next = worker->next->prev = worker; +} + +/* p->mu must be held before calling this function */ +static grpc_error *pollset_kick(grpc_pollset *p, + grpc_pollset_worker *specific_worker) { + GPR_TIMER_BEGIN("pollset_kick", 0); + grpc_error *error = GRPC_ERROR_NONE; + const char *err_desc = "Kick Failure"; + grpc_pollset_worker *worker = specific_worker; + if (worker != NULL) { + if (worker == GRPC_POLLSET_KICK_BROADCAST) { + if (pollset_has_workers(p)) { + GPR_TIMER_BEGIN("pollset_kick.broadcast", 0); + for (worker = p->root_worker.next; worker != &p->root_worker; + worker = worker->next) { + if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { + append_error(&error, pollset_worker_kick(worker), err_desc); + } + } + GPR_TIMER_END("pollset_kick.broadcast", 0); + } else { + p->kicked_without_pollers = true; + } + } else { + GPR_TIMER_MARK("kicked_specifically", 0); + if (gpr_tls_get(&g_current_thread_worker) != (intptr_t)worker) { + append_error(&error, pollset_worker_kick(worker), err_desc); + } + } + } else if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)p) { + /* Since worker == NULL, it means that we can kick "any" worker on this + pollset 'p'. If 'p' happens to be the same pollset this thread is + currently polling (i.e in pollset_work() function), then there is no need + to kick any other worker since the current thread can just absorb the + kick. This is the reason why we enter this case only when + g_current_thread_pollset is != p */ + + GPR_TIMER_MARK("kick_anonymous", 0); + worker = pop_front_worker(p); + if (worker != NULL) { + GPR_TIMER_MARK("finally_kick", 0); + push_back_worker(p, worker); + append_error(&error, pollset_worker_kick(worker), err_desc); + } else { + GPR_TIMER_MARK("kicked_no_pollers", 0); + p->kicked_without_pollers = true; + } + } + + GPR_TIMER_END("pollset_kick", 0); + GRPC_LOG_IF_ERROR("pollset_kick", GRPC_ERROR_REF(error)); + return error; +} + +static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { + gpr_mu_init(&pollset->mu); + *mu = &pollset->mu; + pollset->eps = NULL; + + pollset->root_worker.next = pollset->root_worker.prev = &pollset->root_worker; + pollset->kicked_without_pollers = false; + + pollset->shutting_down = false; + pollset->finish_shutdown_called = false; + pollset->shutdown_done = NULL; +} + +static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { + grpc_lfev_set_ready(exec_ctx, &fd->read_closure); +} + +static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { + grpc_lfev_set_ready(exec_ctx, &fd->write_closure); +} + +static void pollset_release_epoll_set(grpc_exec_ctx *exec_ctx, grpc_pollset *ps, + char *reason) { + if (ps->eps != NULL) { + EPS_UNREF(exec_ctx, ps->eps, reason); + } + ps->eps = NULL; +} + +static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset) { + /* The pollset cannot have any workers if we are at this stage */ + GPR_ASSERT(!pollset_has_workers(pollset)); + + pollset->finish_shutdown_called = true; + + /* Release the ref and set pollset->eps to NULL */ + pollset_release_epoll_set(exec_ctx, pollset, "ps_shutdown"); + grpc_closure_sched(exec_ctx, pollset->shutdown_done, GRPC_ERROR_NONE); +} + +/* pollset->mu lock must be held by the caller before calling this */ +static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_closure *closure) { + GPR_TIMER_BEGIN("pollset_shutdown", 0); + GPR_ASSERT(!pollset->shutting_down); + pollset->shutting_down = true; + pollset->shutdown_done = closure; + pollset_kick(pollset, GRPC_POLLSET_KICK_BROADCAST); + + /* If the pollset has any workers, we cannot call finish_shutdown_locked() + because it would release the underlying epoll set. In such a case, we + let the last worker call finish_shutdown_locked() from pollset_work() */ + if (!pollset_has_workers(pollset)) { + GPR_ASSERT(!pollset->finish_shutdown_called); + GPR_TIMER_MARK("pollset_shutdown.finish_shutdown_locked", 0); + finish_shutdown_locked(exec_ctx, pollset); + } + GPR_TIMER_END("pollset_shutdown", 0); +} + +/* pollset_shutdown is guaranteed to be called before pollset_destroy. So other + * than destroying the mutexes, there is nothing special that needs to be done + * here */ +static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { + GPR_ASSERT(!pollset_has_workers(pollset)); + gpr_mu_destroy(&pollset->mu); +} + +static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx, epoll_set *eps) { + if (gpr_mu_trylock(&eps->workqueue_read_mu)) { + gpr_mpscq_node *n = gpr_mpscq_pop(&eps->workqueue_items); + gpr_mu_unlock(&eps->workqueue_read_mu); + if (n != NULL) { + if (gpr_atm_full_fetch_add(&eps->workqueue_item_count, -1) > 1) { + workqueue_maybe_wakeup(eps); + } + grpc_closure *c = (grpc_closure *)n; + grpc_error *error = c->error_data.error; +#ifndef NDEBUG + c->scheduled = false; +#endif + c->cb(exec_ctx, c->cb_arg, error); + GRPC_ERROR_UNREF(error); + return true; + } else if (gpr_atm_no_barrier_load(&eps->workqueue_item_count) > 0) { + /* n == NULL might mean there's work but it's not available to be popped + * yet - try to ensure another workqueue wakes up to check shortly if so + */ + workqueue_maybe_wakeup(eps); + } + } + return false; +} + +/* Blocking call */ +static void acquire_epoll_lease(epoll_set *eps) { + if (g_num_threads_per_eps > 1) { + gpr_mu_lock(&eps->mu); + } +} + +static void release_epoll_lease(epoll_set *eps) { + if (g_num_threads_per_eps > 1) { + gpr_mu_unlock(&eps->mu); + } +} + +#define GRPC_EPOLL_MAX_EVENTS 100 +static void do_epoll_wait(grpc_exec_ctx *exec_ctx, int epoll_fd, epoll_set *eps, + grpc_error **error) { + struct epoll_event ep_ev[GRPC_EPOLL_MAX_EVENTS]; + int ep_rv; + char *err_msg; + const char *err_desc = "do_epoll_wait"; + + int timeout_ms = -1; + + GRPC_SCHEDULING_START_BLOCKING_REGION; + acquire_epoll_lease(eps); + ep_rv = epoll_wait(epoll_fd, ep_ev, GRPC_EPOLL_MAX_EVENTS, timeout_ms); + release_epoll_lease(eps); + GRPC_SCHEDULING_END_BLOCKING_REGION; + + if (ep_rv < 0) { + gpr_asprintf(&err_msg, + "epoll_wait() epoll fd: %d failed with error: %d (%s)", + epoll_fd, errno, strerror(errno)); + append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); + } + +#ifdef GRPC_TSAN + /* See the definition of g_poll_sync for more details */ + gpr_atm_acq_load(&g_epoll_sync); +#endif /* defined(GRPC_TSAN) */ + + for (int i = 0; i < ep_rv; ++i) { + void *data_ptr = ep_ev[i].data.ptr; + if (data_ptr == &eps->workqueue_wakeup_fd) { + append_error(error, + grpc_wakeup_fd_consume_wakeup(&eps->workqueue_wakeup_fd), + err_desc); + maybe_do_workqueue_work(exec_ctx, eps); + } else if (data_ptr == &epoll_set_wakeup_fd) { + gpr_atm_rel_store(&eps->is_shutdown, 1); + gpr_log(GPR_INFO, "pollset poller: shutdown set"); + } else { + grpc_fd *fd = data_ptr; + int cancel = ep_ev[i].events & (EPOLLERR | EPOLLHUP); + int read_ev = ep_ev[i].events & (EPOLLIN | EPOLLPRI); + int write_ev = ep_ev[i].events & EPOLLOUT; + if (read_ev || cancel) { + fd_become_readable(exec_ctx, fd); + } + if (write_ev || cancel) { + fd_become_writable(exec_ctx, fd); + } + } + } +} + +static void epoll_set_work(grpc_exec_ctx *exec_ctx, epoll_set *eps, + grpc_error **error) { + int epoll_fd = -1; + GPR_TIMER_BEGIN("epoll_set_work", 0); + + /* Since epoll_fd is immutable, it is safe to read it without a lock on the + epoll set. */ + epoll_fd = eps->epoll_fd; + + /* If we get some workqueue work to do, it might end up completing an item on + the completion queue, so there's no need to poll... so we skip that and + redo the complete loop to verify */ + if (!maybe_do_workqueue_work(exec_ctx, eps)) { + gpr_atm_no_barrier_fetch_add(&eps->poller_count, 1); + g_current_thread_epoll_set = eps; + + do_epoll_wait(exec_ctx, epoll_fd, eps, error); + + g_current_thread_epoll_set = NULL; + gpr_atm_no_barrier_fetch_add(&eps->poller_count, -1); + } + + GPR_TIMER_END("epoll_set_work", 0); +} + +/* pollset->mu lock must be held by the caller before calling this. + The function pollset_work() may temporarily release the lock (pollset->mu) + during the course of its execution but it will always re-acquire the lock and + ensure that it is held by the time the function returns */ +static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_pollset_worker **worker_hdl, + gpr_timespec now, gpr_timespec deadline) { + GPR_TIMER_BEGIN("pollset_work", 0); + grpc_error *error = GRPC_ERROR_NONE; + + grpc_pollset_worker worker; + pollset_worker_init(&worker); + + if (worker_hdl) *worker_hdl = &worker; + + gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); + gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); + + if (pollset->kicked_without_pollers) { + /* If the pollset was kicked without pollers, pretend that the current + worker got the kick and skip polling. A kick indicates that there is some + work that needs attention like an event on the completion queue or an + alarm */ + GPR_TIMER_MARK("pollset_work.kicked_without_pollers", 0); + pollset->kicked_without_pollers = 0; + } else if (!pollset->shutting_down) { + push_front_worker(pollset, &worker); + + gpr_cv_wait(&worker.kick_cv, &pollset->mu, + gpr_convert_clock_type(deadline, GPR_CLOCK_REALTIME)); + /* pollset->mu locked here */ + + remove_worker(pollset, &worker); + } + + /* If we are the last worker on the pollset (i.e pollset_has_workers() is + false at this point) and the pollset is shutting down, we may have to + finish the shutdown process by calling finish_shutdown_locked(). + See pollset_shutdown() for more details. + + Note: Continuing to access pollset here is safe; it is the caller's + responsibility to not destroy a pollset when it has outstanding calls to + pollset_work() */ + if (pollset->shutting_down && !pollset_has_workers(pollset) && + !pollset->finish_shutdown_called) { + GPR_TIMER_MARK("pollset_work.finish_shutdown_locked", 0); + finish_shutdown_locked(exec_ctx, pollset); + + gpr_mu_unlock(&pollset->mu); + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(&pollset->mu); + } + + if (worker_hdl) *worker_hdl = NULL; + + gpr_tls_set(&g_current_thread_pollset, (intptr_t)0); + gpr_tls_set(&g_current_thread_worker, (intptr_t)0); + + GPR_TIMER_END("pollset_work", 0); + + GRPC_LOG_IF_ERROR("pollset_work", GRPC_ERROR_REF(error)); + return error; +} + +static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_fd *fd) { + /* Nothing to do */ +} + +/******************************************************************************* + * Pollset-set Definitions + */ +grpc_pollset_set g_dummy_pollset_set; +static grpc_pollset_set *pollset_set_create(void) { + return &g_dummy_pollset_set; +} + +static void pollset_set_destroy(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss) { + /* Nothing to do */ +} + +static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + /* Nothing to do */ +} + +static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + /* Nothing to do */ +} + +static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) { + /* Nothing to do */ +} + +static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) { + /* Nothing to do */ +} + +static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) { + /* Nothing to do */ +} + +static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) { + /* Nothing to do */ +} + +/******************************************************************************* + * Event engine binding + */ + +static void shutdown_engine(void) { + shutdown_poller_threads(); + shutdown_epoll_sets(); + fd_global_shutdown(); + pollset_global_shutdown(); + epoll_set_global_shutdown(); + gpr_log(GPR_INFO, "ev-epoll-threadpool engine shutdown complete"); +} + +static const grpc_event_engine_vtable vtable = { + .pollset_size = sizeof(grpc_pollset), + + .fd_create = fd_create, + .fd_wrapped_fd = fd_wrapped_fd, + .fd_orphan = fd_orphan, + .fd_shutdown = fd_shutdown, + .fd_is_shutdown = fd_is_shutdown, + .fd_notify_on_read = fd_notify_on_read, + .fd_notify_on_write = fd_notify_on_write, + .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, + + .pollset_init = pollset_init, + .pollset_shutdown = pollset_shutdown, + .pollset_destroy = pollset_destroy, + .pollset_work = pollset_work, + .pollset_kick = pollset_kick, + .pollset_add_fd = pollset_add_fd, + + .pollset_set_create = pollset_set_create, + .pollset_set_destroy = pollset_set_destroy, + .pollset_set_add_pollset = pollset_set_add_pollset, + .pollset_set_del_pollset = pollset_set_del_pollset, + .pollset_set_add_pollset_set = pollset_set_add_pollset_set, + .pollset_set_del_pollset_set = pollset_set_del_pollset_set, + .pollset_set_add_fd = pollset_set_add_fd, + .pollset_set_del_fd = pollset_set_del_fd, + + .workqueue_ref = workqueue_ref, + .workqueue_unref = workqueue_unref, + .workqueue_scheduler = workqueue_scheduler, + + .shutdown_engine = shutdown_engine, +}; + +/***************************************************************************** + * Dedicated polling threads and pollsets - Definitions + */ +static void add_fd_to_eps(grpc_fd *fd) { + GPR_ASSERT(fd->eps == NULL); + GPR_TIMER_BEGIN("add_fd_to_eps", 0); + + grpc_error *error = GRPC_ERROR_NONE; + size_t idx = (size_t)gpr_atm_no_barrier_fetch_add(&g_next_eps, 1) % g_num_eps; + epoll_set *eps = g_epoll_sets[idx]; + + gpr_mu_lock(&fd->mu); + + if (fd->orphaned) { + gpr_mu_unlock(&fd->mu); + return; /* Early out */ + } + + epoll_set_add_fd_locked(eps, fd, &error); + EPS_ADD_REF(eps, "fd"); + fd->eps = eps; + + GRPC_POLLING_TRACE("add_fd_to_eps (fd: %d, eps idx = %" PRIdPTR ")", fd->fd, + idx); + gpr_mu_unlock(&fd->mu); + + GRPC_LOG_IF_ERROR("add_fd_to_eps", error); + GPR_TIMER_END("add_fd_to_eps", 0); +} + +static bool init_epoll_sets() { + grpc_error *error = GRPC_ERROR_NONE; + bool is_success = true; + + g_epoll_sets = (epoll_set **)malloc(g_num_eps * sizeof(epoll_set *)); + + for (size_t i = 0; i < g_num_eps; i++) { + g_epoll_sets[i] = epoll_set_create(&error); + if (g_epoll_sets[i] == NULL) { + gpr_log(GPR_ERROR, "Error in creating a epoll set"); + g_num_eps = i; /* Helps cleanup */ + shutdown_epoll_sets(); + is_success = false; + goto done; + } + + EPS_ADD_REF(g_epoll_sets[i], "init_epoll_sets"); + } + + gpr_atm_no_barrier_store(&g_next_eps, 0); + gpr_mu *mu; + pollset_init(&g_read_notifier, &mu); + +done: + GRPC_LOG_IF_ERROR("init_epoll_sets", error); + return is_success; +} + +static void shutdown_epoll_sets() { + if (!g_epoll_sets) { + return; + } + + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + for (size_t i = 0; i < g_num_eps; i++) { + EPS_UNREF(&exec_ctx, g_epoll_sets[i], "shutdown_epoll_sets"); + } + grpc_exec_ctx_flush(&exec_ctx); + + gpr_free(g_epoll_sets); + g_epoll_sets = NULL; + pollset_destroy(&exec_ctx, &g_read_notifier); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void poller_thread_loop(void *arg) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_error *error = GRPC_ERROR_NONE; + epoll_set *eps = (epoll_set *)arg; + + while (!gpr_atm_acq_load(&eps->is_shutdown)) { + epoll_set_work(&exec_ctx, eps, &error); + grpc_exec_ctx_flush(&exec_ctx); + } + + grpc_exec_ctx_finish(&exec_ctx); + GRPC_LOG_IF_ERROR("poller_thread_loop", error); +} + +/* g_epoll_sets MUST be initialized before calling this */ +static void start_poller_threads() { + GPR_ASSERT(g_epoll_sets); + + gpr_log(GPR_INFO, "Starting poller threads"); + + size_t num_threads = g_num_eps * g_num_threads_per_eps; + g_poller_threads = (gpr_thd_id *)malloc(num_threads * sizeof(gpr_thd_id)); + gpr_thd_options options = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&options); + + for (size_t i = 0; i < num_threads; i++) { + gpr_thd_new(&g_poller_threads[i], poller_thread_loop, + (void *)g_epoll_sets[i % g_num_eps], &options); + } +} + +static void shutdown_poller_threads() { + GPR_ASSERT(g_poller_threads); + GPR_ASSERT(g_epoll_sets); + grpc_error *error = GRPC_ERROR_NONE; + + gpr_log(GPR_INFO, "Shutting down pollers"); + + epoll_set *eps = NULL; + size_t num_threads = g_num_eps * g_num_threads_per_eps; + for (size_t i = 0; i < num_threads; i++) { + eps = g_epoll_sets[i]; + epoll_set_add_wakeup_fd_locked(eps, &epoll_set_wakeup_fd, &error); + } + + for (size_t i = 0; i < g_num_eps; i++) { + gpr_thd_join(g_poller_threads[i]); + } + + GRPC_LOG_IF_ERROR("shutdown_poller_threads", error); + gpr_free(g_poller_threads); + g_poller_threads = NULL; +} + +/****************************************************************************/ + +/* It is possible that GLIBC has epoll but the underlying kernel doesn't. + * Create a dummy epoll_fd to make sure epoll support is available */ +static bool is_epoll_available() { + int fd = epoll_create1(EPOLL_CLOEXEC); + if (fd < 0) { + gpr_log( + GPR_ERROR, + "epoll_create1 failed with error: %d. Not using epoll polling engine", + fd); + return false; + } + close(fd); + return true; +} + +const grpc_event_engine_vtable *grpc_init_epoll_thread_pool_linux( + bool requested_explicitly) { + if (!requested_explicitly) return NULL; + + if (!grpc_has_wakeup_fd()) { + return NULL; + } + + if (!is_epoll_available()) { + return NULL; + } + + fd_global_init(); + + if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { + return NULL; + } + + if (!GRPC_LOG_IF_ERROR("epoll_set_global_init", epoll_set_global_init())) { + return NULL; + } + + if (!init_epoll_sets()) { + return NULL; + } + + /* TODO (sreek): Maynot be a good idea to start threads here (especially if + * this engine doesn't get picked. Consider introducing an engine_init + * function in the vtable */ + start_poller_threads(); + return &vtable; +} + +#else /* defined(GRPC_LINUX_EPOLL) */ +#if defined(GRPC_POSIX_SOCKET) +#include "src/core/lib/iomgr/ev_posix.h" +/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return + * NULL */ +const grpc_event_engine_vtable *grpc_init_epoll_thread_pool_linux( + bool requested_explicitly) { + return NULL; +} +#endif /* defined(GRPC_POSIX_SOCKET) */ +#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..9af776a52e9fce066b0807e4da07300bbf7b4a3a --- /dev/null +++ b/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL_THREAD_POOL_LINUX_H +#define GRPC_CORE_LIB_IOMGR_EV_EPOLL_THREAD_POOL_LINUX_H + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/port.h" + +const grpc_event_engine_vtable *grpc_init_epoll_thread_pool_linux( + bool requested_explicitly); + +#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL_THREAD_POOL_LINUX_H */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.c b/src/core/lib/iomgr/ev_epollex_linux.c new file mode 100644 index 0000000000000000000000000000000000000000..7cb6085e25517bc1f7a92c86aad3ee004efa7abc --- /dev/null +++ b/src/core/lib/iomgr/ev_epollex_linux.c @@ -0,0 +1,1511 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +/* This polling engine is only relevant on linux kernels supporting epoll() */ +#ifdef GRPC_LINUX_EPOLL + +#include "src/core/lib/iomgr/ev_epollex_linux.h" + +#include <assert.h> +#include <errno.h> +#include <poll.h> +#include <pthread.h> +#include <string.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/tls.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/iomgr_internal.h" +#include "src/core/lib/iomgr/is_epollexclusive_available.h" +#include "src/core/lib/iomgr/lockfree_event.h" +#include "src/core/lib/iomgr/sys_epoll_wrapper.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/iomgr/wakeup_fd_posix.h" +#include "src/core/lib/iomgr/workqueue.h" +#include "src/core/lib/profiling/timers.h" +#include "src/core/lib/support/block_annotate.h" +#include "src/core/lib/support/spinlock.h" + +/******************************************************************************* + * Pollset-set sibling link + */ + +typedef enum { + PO_POLLING_GROUP, + PO_POLLSET_SET, + PO_POLLSET, + PO_FD, /* ordering is important: we always want to lock pollsets before fds: + this guarantees that using an fd as a pollable is safe */ + PO_EMPTY_POLLABLE, + PO_COUNT +} polling_obj_type; + +typedef struct polling_obj polling_obj; +typedef struct polling_group polling_group; + +struct polling_obj { + gpr_mu mu; + polling_obj_type type; + polling_group *group; + struct polling_obj *next; + struct polling_obj *prev; +}; + +struct polling_group { + polling_obj po; + gpr_refcount refs; +}; + +static void po_init(polling_obj *po, polling_obj_type type); +static void po_destroy(polling_obj *po); +static void po_join(grpc_exec_ctx *exec_ctx, polling_obj *a, polling_obj *b); +static int po_cmp(polling_obj *a, polling_obj *b); + +static void pg_create(grpc_exec_ctx *exec_ctx, polling_obj **initial_po, + size_t initial_po_count); +static polling_group *pg_ref(polling_group *pg); +static void pg_unref(polling_group *pg); +static void pg_merge(grpc_exec_ctx *exec_ctx, polling_group *a, + polling_group *b); +static void pg_join(grpc_exec_ctx *exec_ctx, polling_group *pg, + polling_obj *po); + +/******************************************************************************* + * pollable Declarations + */ + +typedef struct pollable { + polling_obj po; + int epfd; + grpc_wakeup_fd wakeup; + grpc_pollset_worker *root_worker; +} pollable; + +static pollable g_empty_pollable; + +static void pollable_init(pollable *p, polling_obj_type type); +static void pollable_destroy(pollable *p); +/* ensure that p->epfd, p->wakeup are initialized; p->po.mu must be held */ +static grpc_error *pollable_materialize(pollable *p); + +/******************************************************************************* + * Fd Declarations + */ + +struct grpc_fd { + pollable pollable; + int fd; + /* refst format: + bit 0 : 1=Active / 0=Orphaned + bits 1-n : refcount + Ref/Unref by two to avoid altering the orphaned bit */ + gpr_atm refst; + + /* Wakeup fd used to wake pollers to check the contents of workqueue_items */ + grpc_wakeup_fd workqueue_wakeup_fd; + grpc_closure_scheduler workqueue_scheduler; + /* Spinlock guarding the read end of the workqueue (must be held to pop from + * workqueue_items) */ + gpr_spinlock workqueue_read_mu; + /* Queue of closures to be executed */ + gpr_mpscq workqueue_items; + /* Count of items in workqueue_items */ + gpr_atm workqueue_item_count; + + /* The fd is either closed or we relinquished control of it. In either + cases, this indicates that the 'fd' on this structure is no longer + valid */ + gpr_mu orphaned_mu; + bool orphaned; + + gpr_atm read_closure; + gpr_atm write_closure; + + struct grpc_fd *freelist_next; + grpc_closure *on_done_closure; + + /* The pollset that last noticed that the fd is readable. The actual type + * stored in this is (grpc_pollset *) */ + gpr_atm read_notifier_pollset; + + grpc_iomgr_object iomgr_object; +}; + +static void fd_global_init(void); +static void fd_global_shutdown(void); + +static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error); + +static const grpc_closure_scheduler_vtable workqueue_scheduler_vtable = { + workqueue_enqueue, workqueue_enqueue, "workqueue"}; + +/******************************************************************************* + * Pollset Declarations + */ + +typedef struct pollset_worker_link { + grpc_pollset_worker *next; + grpc_pollset_worker *prev; +} pollset_worker_link; + +typedef enum { + PWL_POLLSET, + PWL_POLLABLE, + POLLSET_WORKER_LINK_COUNT +} pollset_worker_links; + +struct grpc_pollset_worker { + bool kicked; + bool initialized_cv; + pollset_worker_link links[POLLSET_WORKER_LINK_COUNT]; + gpr_cv cv; + grpc_pollset *pollset; + pollable *pollable; +}; + +struct grpc_pollset { + pollable pollable; + pollable *current_pollable; + bool kicked_without_poller; + grpc_closure *shutdown_closure; + grpc_pollset_worker *root_worker; +}; + +/******************************************************************************* + * Pollset-set Declarations + */ +struct grpc_pollset_set { + polling_obj po; +}; + +/******************************************************************************* + * Common helpers + */ + +static bool append_error(grpc_error **composite, grpc_error *error, + const char *desc) { + if (error == GRPC_ERROR_NONE) return true; + if (*composite == GRPC_ERROR_NONE) { + *composite = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); + } + *composite = grpc_error_add_child(*composite, error); + return false; +} + +/******************************************************************************* + * Fd Definitions + */ + +/* We need to keep a freelist not because of any concerns of malloc performance + * but instead so that implementations with multiple threads in (for example) + * epoll_wait deal with the race between pollset removal and incoming poll + * notifications. + * + * The problem is that the poller ultimately holds a reference to this + * object, so it is very difficult to know when is safe to free it, at least + * without some expensive synchronization. + * + * If we keep the object freelisted, in the worst case losing this race just + * becomes a spurious read notification on a reused fd. + */ + +/* The alarm system needs to be able to wakeup 'some poller' sometimes + * (specifically when a new alarm needs to be triggered earlier than the next + * alarm 'epoch'). This wakeup_fd gives us something to alert on when such a + * case occurs. */ + +static grpc_fd *fd_freelist = NULL; +static gpr_mu fd_freelist_mu; + +#ifdef GRPC_FD_REF_COUNT_DEBUG +#define REF_BY(fd, n, reason) ref_by(fd, n, reason, __FILE__, __LINE__) +#define UNREF_BY(ec, fd, n, reason) \ + unref_by(ec, fd, n, reason, __FILE__, __LINE__) +static void ref_by(grpc_fd *fd, int n, const char *reason, const char *file, + int line) { + gpr_log(GPR_DEBUG, "FD %d %p ref %d %ld -> %ld [%s; %s:%d]", fd->fd, + (void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), + gpr_atm_no_barrier_load(&fd->refst) + n, reason, file, line); +#else +#define REF_BY(fd, n, reason) ref_by(fd, n) +#define UNREF_BY(ec, fd, n, reason) unref_by(ec, fd, n) +static void ref_by(grpc_fd *fd, int n) { +#endif + GPR_ASSERT(gpr_atm_no_barrier_fetch_add(&fd->refst, n) > 0); +} + +static void fd_destroy(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { + grpc_fd *fd = arg; + /* Add the fd to the freelist */ + grpc_iomgr_unregister_object(&fd->iomgr_object); + pollable_destroy(&fd->pollable); + gpr_mu_destroy(&fd->orphaned_mu); + gpr_mu_lock(&fd_freelist_mu); + fd->freelist_next = fd_freelist; + fd_freelist = fd; + + grpc_lfev_destroy(&fd->read_closure); + grpc_lfev_destroy(&fd->write_closure); + + gpr_mu_unlock(&fd_freelist_mu); +} + +#ifdef GRPC_FD_REF_COUNT_DEBUG +static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n, + const char *reason, const char *file, int line) { + gpr_atm old; + gpr_log(GPR_DEBUG, "FD %d %p unref %d %ld -> %ld [%s; %s:%d]", fd->fd, + (void *)fd, n, gpr_atm_no_barrier_load(&fd->refst), + gpr_atm_no_barrier_load(&fd->refst) - n, reason, file, line); +#else +static void unref_by(grpc_exec_ctx *exec_ctx, grpc_fd *fd, int n) { + gpr_atm old; +#endif + old = gpr_atm_full_fetch_add(&fd->refst, -n); + if (old == n) { + grpc_closure_sched(exec_ctx, grpc_closure_create(fd_destroy, fd, + grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); + } else { + GPR_ASSERT(old > n); + } +} + +static void fd_global_init(void) { gpr_mu_init(&fd_freelist_mu); } + +static void fd_global_shutdown(void) { + gpr_mu_lock(&fd_freelist_mu); + gpr_mu_unlock(&fd_freelist_mu); + while (fd_freelist != NULL) { + grpc_fd *fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + gpr_free(fd); + } + gpr_mu_destroy(&fd_freelist_mu); +} + +static grpc_fd *fd_create(int fd, const char *name) { + grpc_fd *new_fd = NULL; + + gpr_mu_lock(&fd_freelist_mu); + if (fd_freelist != NULL) { + new_fd = fd_freelist; + fd_freelist = fd_freelist->freelist_next; + } + gpr_mu_unlock(&fd_freelist_mu); + + if (new_fd == NULL) { + new_fd = gpr_malloc(sizeof(grpc_fd)); + } + + pollable_init(&new_fd->pollable, PO_FD); + + gpr_atm_rel_store(&new_fd->refst, (gpr_atm)1); + new_fd->fd = fd; + gpr_mu_init(&new_fd->orphaned_mu); + new_fd->orphaned = false; + grpc_lfev_init(&new_fd->read_closure); + grpc_lfev_init(&new_fd->write_closure); + gpr_atm_no_barrier_store(&new_fd->read_notifier_pollset, (gpr_atm)NULL); + + GRPC_LOG_IF_ERROR("fd_create", + grpc_wakeup_fd_init(&new_fd->workqueue_wakeup_fd)); + new_fd->workqueue_scheduler.vtable = &workqueue_scheduler_vtable; + new_fd->workqueue_read_mu = GPR_SPINLOCK_INITIALIZER; + gpr_mpscq_init(&new_fd->workqueue_items); + gpr_atm_no_barrier_store(&new_fd->workqueue_item_count, 0); + + new_fd->freelist_next = NULL; + new_fd->on_done_closure = NULL; + + char *fd_name; + gpr_asprintf(&fd_name, "%s fd=%d", name, fd); + grpc_iomgr_register_object(&new_fd->iomgr_object, fd_name); +#ifdef GRPC_FD_REF_COUNT_DEBUG + gpr_log(GPR_DEBUG, "FD %d %p create %s", fd, (void *)new_fd, fd_name); +#endif + gpr_free(fd_name); + return new_fd; +} + +static int fd_wrapped_fd(grpc_fd *fd) { + int ret_fd = -1; + gpr_mu_lock(&fd->orphaned_mu); + if (!fd->orphaned) { + ret_fd = fd->fd; + } + gpr_mu_unlock(&fd->orphaned_mu); + + return ret_fd; +} + +static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *on_done, int *release_fd, + const char *reason) { + bool is_fd_closed = false; + grpc_error *error = GRPC_ERROR_NONE; + + gpr_mu_lock(&fd->pollable.po.mu); + gpr_mu_lock(&fd->orphaned_mu); + fd->on_done_closure = on_done; + + /* If release_fd is not NULL, we should be relinquishing control of the file + descriptor fd->fd (but we still own the grpc_fd structure). */ + if (release_fd != NULL) { + *release_fd = fd->fd; + } else { + close(fd->fd); + is_fd_closed = true; + } + + fd->orphaned = true; + + if (!is_fd_closed) { + gpr_log(GPR_DEBUG, "TODO: handle fd removal?"); + } + + /* Remove the active status but keep referenced. We want this grpc_fd struct + to be alive (and not added to freelist) until the end of this function */ + REF_BY(fd, 1, reason); + + grpc_closure_sched(exec_ctx, fd->on_done_closure, GRPC_ERROR_REF(error)); + + gpr_mu_unlock(&fd->orphaned_mu); + gpr_mu_unlock(&fd->pollable.po.mu); + UNREF_BY(exec_ctx, fd, 2, reason); /* Drop the reference */ + GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error)); + GRPC_ERROR_UNREF(error); +} + +static grpc_pollset *fd_get_read_notifier_pollset(grpc_exec_ctx *exec_ctx, + grpc_fd *fd) { + gpr_atm notifier = gpr_atm_acq_load(&fd->read_notifier_pollset); + return (grpc_pollset *)notifier; +} + +static bool fd_is_shutdown(grpc_fd *fd) { + return grpc_lfev_is_shutdown(&fd->read_closure); +} + +/* Might be called multiple times */ +static void fd_shutdown(grpc_exec_ctx *exec_ctx, grpc_fd *fd, grpc_error *why) { + if (grpc_lfev_set_shutdown(exec_ctx, &fd->read_closure, + GRPC_ERROR_REF(why))) { + shutdown(fd->fd, SHUT_RDWR); + grpc_lfev_set_shutdown(exec_ctx, &fd->write_closure, GRPC_ERROR_REF(why)); + } + GRPC_ERROR_UNREF(why); +} + +static void fd_notify_on_read(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->read_closure, closure); +} + +static void fd_notify_on_write(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_closure *closure) { + grpc_lfev_notify_on(exec_ctx, &fd->write_closure, closure); +} + +static grpc_workqueue *fd_get_workqueue(grpc_fd *fd) { + REF_BY(fd, 2, "return_workqueue"); + return (grpc_workqueue *)fd; +} + +#ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue, + const char *file, int line, + const char *reason) { + if (workqueue != NULL) { + ref_by((grpc_fd *)workqueue, 2, file, line, reason); + } + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue, + const char *file, int line, const char *reason) { + if (workqueue != NULL) { + unref_by(exec_ctx, (grpc_fd *)workqueue, 2, file, line, reason); + } +} +#else +static grpc_workqueue *workqueue_ref(grpc_workqueue *workqueue) { + if (workqueue != NULL) { + ref_by((grpc_fd *)workqueue, 2); + } + return workqueue; +} + +static void workqueue_unref(grpc_exec_ctx *exec_ctx, + grpc_workqueue *workqueue) { + if (workqueue != NULL) { + unref_by(exec_ctx, (grpc_fd *)workqueue, 2); + } +} +#endif + +static void workqueue_wakeup(grpc_fd *fd) { + GRPC_LOG_IF_ERROR("workqueue_enqueue", + grpc_wakeup_fd_wakeup(&fd->workqueue_wakeup_fd)); +} + +static void workqueue_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure, + grpc_error *error) { + GPR_TIMER_BEGIN("workqueue.enqueue", 0); + grpc_fd *fd = (grpc_fd *)(((char *)closure->scheduler) - + offsetof(grpc_fd, workqueue_scheduler)); + REF_BY(fd, 2, "workqueue_enqueue"); + gpr_atm last = gpr_atm_no_barrier_fetch_add(&fd->workqueue_item_count, 1); + closure->error_data.error = error; + gpr_mpscq_push(&fd->workqueue_items, &closure->next_data.atm_next); + if (last == 0) { + workqueue_wakeup(fd); + } + UNREF_BY(exec_ctx, fd, 2, "workqueue_enqueue"); +} + +static void fd_invoke_workqueue(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { + /* handle spurious wakeups */ + if (!gpr_spinlock_trylock(&fd->workqueue_read_mu)) return; + gpr_mpscq_node *n = gpr_mpscq_pop(&fd->workqueue_items); + gpr_spinlock_unlock(&fd->workqueue_read_mu); + if (n != NULL) { + if (gpr_atm_full_fetch_add(&fd->workqueue_item_count, -1) > 1) { + workqueue_wakeup(fd); + } + grpc_closure *c = (grpc_closure *)n; + grpc_error *error = c->error_data.error; +#ifndef NDEBUG + c->scheduled = false; +#endif + c->cb(exec_ctx, c->cb_arg, error); + GRPC_ERROR_UNREF(error); + } else if (gpr_atm_no_barrier_load(&fd->workqueue_item_count) > 0) { + /* n == NULL might mean there's work but it's not available to be popped + * yet - try to ensure another workqueue wakes up to check shortly if so + */ + workqueue_wakeup(fd); + } +} + +static grpc_closure_scheduler *workqueue_scheduler(grpc_workqueue *workqueue) { + return &((grpc_fd *)workqueue)->workqueue_scheduler; +} + +/******************************************************************************* + * Pollable Definitions + */ + +static void pollable_init(pollable *p, polling_obj_type type) { + po_init(&p->po, type); + p->root_worker = NULL; + p->epfd = -1; +} + +static void pollable_destroy(pollable *p) { + po_destroy(&p->po); + if (p->epfd != -1) { + close(p->epfd); + grpc_wakeup_fd_destroy(&p->wakeup); + } +} + +/* ensure that p->epfd, p->wakeup are initialized; p->po.mu must be held */ +static grpc_error *pollable_materialize(pollable *p) { + if (p->epfd == -1) { + int new_epfd = epoll_create1(EPOLL_CLOEXEC); + if (new_epfd < 0) { + return GRPC_OS_ERROR(errno, "epoll_create1"); + } + grpc_error *err = grpc_wakeup_fd_init(&p->wakeup); + if (err != GRPC_ERROR_NONE) { + close(new_epfd); + return err; + } + struct epoll_event ev = {.events = (uint32_t)(EPOLLIN | EPOLLET), + .data.ptr = &p->wakeup}; + if (epoll_ctl(new_epfd, EPOLL_CTL_ADD, p->wakeup.read_fd, &ev) != 0) { + err = GRPC_OS_ERROR(errno, "epoll_ctl"); + close(new_epfd); + grpc_wakeup_fd_destroy(&p->wakeup); + return err; + } + + p->epfd = new_epfd; + } + return GRPC_ERROR_NONE; +} + +/* pollable must be materialized */ +static grpc_error *pollable_add_fd(pollable *p, grpc_fd *fd) { + grpc_error *error = GRPC_ERROR_NONE; + static const char *err_desc = "pollable_add_fd"; + const int epfd = p->epfd; + GPR_ASSERT(epfd != -1); + + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "add fd %p to pollable %p", fd, p); + } + + gpr_mu_lock(&fd->orphaned_mu); + if (fd->orphaned) { + gpr_mu_unlock(&fd->orphaned_mu); + return GRPC_ERROR_NONE; + } + struct epoll_event ev_fd = { + .events = (uint32_t)(EPOLLET | EPOLLIN | EPOLLOUT | EPOLLEXCLUSIVE), + .data.ptr = fd}; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->fd, &ev_fd) != 0) { + switch (errno) { + case EEXIST: /* if this fd is already in the epoll set, the workqueue fd + must also be - just return */ + gpr_mu_unlock(&fd->orphaned_mu); + return GRPC_ERROR_NONE; + default: + append_error(&error, GRPC_OS_ERROR(errno, "epoll_ctl"), err_desc); + } + } + struct epoll_event ev_wq = { + .events = (uint32_t)(EPOLLET | EPOLLIN | EPOLLEXCLUSIVE), + .data.ptr = (void *)(1 + (intptr_t)fd)}; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd->workqueue_wakeup_fd.read_fd, &ev_wq) != + 0) { + switch (errno) { + case EEXIST: /* if the workqueue fd is already in the epoll set we're ok + - no need to do anything special */ + break; + default: + append_error(&error, GRPC_OS_ERROR(errno, "epoll_ctl"), err_desc); + } + } + gpr_mu_unlock(&fd->orphaned_mu); + + return error; +} + +/******************************************************************************* + * Pollset Definitions + */ + +GPR_TLS_DECL(g_current_thread_pollset); +GPR_TLS_DECL(g_current_thread_worker); + +/* Global state management */ +static grpc_error *pollset_global_init(void) { + gpr_tls_init(&g_current_thread_pollset); + gpr_tls_init(&g_current_thread_worker); + pollable_init(&g_empty_pollable, PO_EMPTY_POLLABLE); + return GRPC_ERROR_NONE; +} + +static void pollset_global_shutdown(void) { + pollable_destroy(&g_empty_pollable); + gpr_tls_destroy(&g_current_thread_pollset); + gpr_tls_destroy(&g_current_thread_worker); +} + +static grpc_error *pollset_kick_all(grpc_pollset *pollset) { + grpc_error *error = GRPC_ERROR_NONE; + if (pollset->root_worker != NULL) { + grpc_pollset_worker *worker = pollset->root_worker; + do { + if (worker->pollable != &pollset->pollable) { + gpr_mu_lock(&worker->pollable->po.mu); + } + if (worker->initialized_cv) { + worker->kicked = true; + gpr_cv_signal(&worker->cv); + } else { + append_error(&error, grpc_wakeup_fd_wakeup(&worker->pollable->wakeup), + "pollset_shutdown"); + } + if (worker->pollable != &pollset->pollable) { + gpr_mu_unlock(&worker->pollable->po.mu); + } + + worker = worker->links[PWL_POLLSET].next; + } while (worker != pollset->root_worker); + } + return error; +} + +static grpc_error *pollset_kick_inner(grpc_pollset *pollset, pollable *p, + grpc_pollset_worker *specific_worker) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, + "PS:%p kick %p tls_pollset=%p tls_worker=%p " + "root_worker=(pollset:%p pollable:%p)", + p, specific_worker, (void *)gpr_tls_get(&g_current_thread_pollset), + (void *)gpr_tls_get(&g_current_thread_worker), pollset->root_worker, + p->root_worker); + } + if (specific_worker == NULL) { + if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) { + if (pollset->root_worker == NULL) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_any_without_poller", p); + } + pollset->kicked_without_poller = true; + return GRPC_ERROR_NONE; + } else { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_any_via_wakeup_fd", p); + } + grpc_error *err = pollable_materialize(p); + if (err != GRPC_ERROR_NONE) return err; + return grpc_wakeup_fd_wakeup(&p->wakeup); + } + } else { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_any_but_awake", p); + } + return GRPC_ERROR_NONE; + } + } else if (specific_worker->kicked) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_already_kicked", p); + } + return GRPC_ERROR_NONE; + } else if (gpr_tls_get(&g_current_thread_worker) == + (intptr_t)specific_worker) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_awake", p); + } + specific_worker->kicked = true; + return GRPC_ERROR_NONE; + } else if (specific_worker == p->root_worker) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_wakeup_fd", p); + } + grpc_error *err = pollable_materialize(p); + if (err != GRPC_ERROR_NONE) return err; + specific_worker->kicked = true; + return grpc_wakeup_fd_wakeup(&p->wakeup); + } else { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_cv", p); + } + specific_worker->kicked = true; + gpr_cv_signal(&specific_worker->cv); + return GRPC_ERROR_NONE; + } +} + +/* p->po.mu must be held before calling this function */ +static grpc_error *pollset_kick(grpc_pollset *pollset, + grpc_pollset_worker *specific_worker) { + pollable *p = pollset->current_pollable; + if (p != &pollset->pollable) { + gpr_mu_lock(&p->po.mu); + } + grpc_error *error = pollset_kick_inner(pollset, p, specific_worker); + if (p != &pollset->pollable) { + gpr_mu_unlock(&p->po.mu); + } + return error; +} + +static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { + pollable_init(&pollset->pollable, PO_POLLSET); + pollset->current_pollable = &g_empty_pollable; + pollset->kicked_without_poller = false; + pollset->shutdown_closure = NULL; + pollset->root_worker = NULL; + *mu = &pollset->pollable.po.mu; +} + +/* Convert a timespec to milliseconds: + - Very small or negative poll times are clamped to zero to do a non-blocking + poll (which becomes spin polling) + - Other small values are rounded up to one millisecond + - Longer than a millisecond polls are rounded up to the next nearest + millisecond to avoid spinning + - Infinite timeouts are converted to -1 */ +static int poll_deadline_to_millis_timeout(gpr_timespec deadline, + gpr_timespec now) { + gpr_timespec timeout; + if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) { + return -1; + } + + if (gpr_time_cmp(deadline, now) <= 0) { + return 0; + } + + static const gpr_timespec round_up = { + .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1}; + timeout = gpr_time_sub(deadline, now); + int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up)); + return millis >= 1 ? millis : 1; +} + +static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd, + grpc_pollset *notifier) { + grpc_lfev_set_ready(exec_ctx, &fd->read_closure); + + /* Note, it is possible that fd_become_readable might be called twice with + different 'notifier's when an fd becomes readable and it is in two epoll + sets (This can happen briefly during polling island merges). In such cases + it does not really matter which notifer is set as the read_notifier_pollset + (They would both point to the same polling island anyway) */ + /* Use release store to match with acquire load in fd_get_read_notifier */ + gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier); +} + +static void fd_become_writable(grpc_exec_ctx *exec_ctx, grpc_fd *fd) { + grpc_lfev_set_ready(exec_ctx, &fd->write_closure); +} + +static grpc_error *fd_become_pollable_locked(grpc_fd *fd) { + grpc_error *error = GRPC_ERROR_NONE; + static const char *err_desc = "fd_become_pollable"; + if (append_error(&error, pollable_materialize(&fd->pollable), err_desc)) { + append_error(&error, pollable_add_fd(&fd->pollable, fd), err_desc); + } + return error; +} + +static void pollset_maybe_finish_shutdown(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset) { + if (pollset->shutdown_closure != NULL && pollset->root_worker == NULL) { + grpc_closure_sched(exec_ctx, pollset->shutdown_closure, GRPC_ERROR_NONE); + pollset->shutdown_closure = NULL; + } +} + +/* pollset->po.mu lock must be held by the caller before calling this */ +static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_closure *closure) { + GPR_ASSERT(pollset->shutdown_closure == NULL); + pollset->shutdown_closure = closure; + GRPC_LOG_IF_ERROR("pollset_shutdown", pollset_kick_all(pollset)); + pollset_maybe_finish_shutdown(exec_ctx, pollset); +} + +static bool pollset_is_pollable_fd(grpc_pollset *pollset, pollable *p) { + return p != &g_empty_pollable && p != &pollset->pollable; +} + +/* pollset_shutdown is guaranteed to be called before pollset_destroy. */ +static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { + pollable_destroy(&pollset->pollable); + if (pollset_is_pollable_fd(pollset, pollset->current_pollable)) { + UNREF_BY(exec_ctx, (grpc_fd *)pollset->current_pollable, 2, + "pollset_pollable"); + } +} + +#define MAX_EPOLL_EVENTS 100 + +static grpc_error *pollset_epoll(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + pollable *p, gpr_timespec now, + gpr_timespec deadline) { + struct epoll_event events[MAX_EPOLL_EVENTS]; + static const char *err_desc = "pollset_poll"; + + int timeout = poll_deadline_to_millis_timeout(deadline, now); + + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p poll %p for %dms", pollset, p, timeout); + } + + if (timeout != 0) { + GRPC_SCHEDULING_START_BLOCKING_REGION; + } + int r; + do { + r = epoll_wait(p->epfd, events, MAX_EPOLL_EVENTS, timeout); + } while (r < 0 && errno == EINTR); + if (timeout != 0) { + GRPC_SCHEDULING_END_BLOCKING_REGION; + } + + if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait"); + + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p poll %p got %d events", pollset, p, r); + } + + grpc_error *error = GRPC_ERROR_NONE; + for (int i = 0; i < r; i++) { + void *data_ptr = events[i].data.ptr; + if (data_ptr == &p->wakeup) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p poll %p got pollset_wakeup", pollset, p); + } + append_error(&error, grpc_wakeup_fd_consume_wakeup(&p->wakeup), err_desc); + } else { + grpc_fd *fd = (grpc_fd *)(((intptr_t)data_ptr) & ~(intptr_t)1); + bool is_workqueue = (((intptr_t)data_ptr) & 1) != 0; + bool cancel = (events[i].events & (EPOLLERR | EPOLLHUP)) != 0; + bool read_ev = (events[i].events & (EPOLLIN | EPOLLPRI)) != 0; + bool write_ev = (events[i].events & EPOLLOUT) != 0; + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, + "PS:%p poll %p got fd %p: is_wq=%d cancel=%d read=%d " + "write=%d", + pollset, p, fd, is_workqueue, cancel, read_ev, write_ev); + } + if (is_workqueue) { + append_error(&error, + grpc_wakeup_fd_consume_wakeup(&fd->workqueue_wakeup_fd), + err_desc); + fd_invoke_workqueue(exec_ctx, fd); + } else { + if (read_ev || cancel) { + fd_become_readable(exec_ctx, fd, pollset); + } + if (write_ev || cancel) { + fd_become_writable(exec_ctx, fd); + } + } + } + } + + return error; +} + +/* Return true if first in list */ +static bool worker_insert(grpc_pollset_worker **root, pollset_worker_links link, + grpc_pollset_worker *worker) { + if (*root == NULL) { + *root = worker; + worker->links[link].next = worker->links[link].prev = worker; + return true; + } else { + worker->links[link].next = *root; + worker->links[link].prev = worker->links[link].next->links[link].prev; + worker->links[link].next->links[link].prev = worker; + worker->links[link].prev->links[link].next = worker; + return false; + } +} + +/* Return true if last in list */ +typedef enum { EMPTIED, NEW_ROOT, REMOVED } worker_remove_result; + +static worker_remove_result worker_remove(grpc_pollset_worker **root, + pollset_worker_links link, + grpc_pollset_worker *worker) { + if (worker == *root) { + if (worker == worker->links[link].next) { + *root = NULL; + return EMPTIED; + } else { + *root = worker->links[link].next; + worker->links[link].prev->links[link].next = worker->links[link].next; + worker->links[link].next->links[link].prev = worker->links[link].prev; + return NEW_ROOT; + } + } else { + worker->links[link].prev->links[link].next = worker->links[link].next; + worker->links[link].next->links[link].prev = worker->links[link].prev; + return REMOVED; + } +} + +/* Return true if this thread should poll */ +static bool begin_worker(grpc_pollset *pollset, grpc_pollset_worker *worker, + grpc_pollset_worker **worker_hdl, gpr_timespec *now, + gpr_timespec deadline) { + bool do_poll = true; + if (worker_hdl != NULL) *worker_hdl = worker; + worker->initialized_cv = false; + worker->kicked = false; + worker->pollset = pollset; + worker->pollable = pollset->current_pollable; + + if (pollset_is_pollable_fd(pollset, worker->pollable)) { + REF_BY((grpc_fd *)worker->pollable, 2, "one_poll"); + } + + worker_insert(&pollset->root_worker, PWL_POLLSET, worker); + if (!worker_insert(&worker->pollable->root_worker, PWL_POLLABLE, worker)) { + worker->initialized_cv = true; + gpr_cv_init(&worker->cv); + if (worker->pollable != &pollset->pollable) { + gpr_mu_unlock(&pollset->pollable.po.mu); + } + if (GRPC_TRACER_ON(grpc_polling_trace) && + worker->pollable->root_worker != worker) { + gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset, + worker->pollable, worker, + poll_deadline_to_millis_timeout(deadline, *now)); + } + while (do_poll && worker->pollable->root_worker != worker) { + if (gpr_cv_wait(&worker->cv, &worker->pollable->po.mu, deadline)) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset, + worker->pollable, worker); + } + do_poll = false; + } else if (worker->kicked) { + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p wakeup %p w=%p", pollset, worker->pollable, + worker); + } + do_poll = false; + } else if (GRPC_TRACER_ON(grpc_polling_trace) && + worker->pollable->root_worker != worker) { + gpr_log(GPR_DEBUG, "PS:%p spurious_wakeup %p w=%p", pollset, + worker->pollable, worker); + } + } + if (worker->pollable != &pollset->pollable) { + gpr_mu_unlock(&worker->pollable->po.mu); + gpr_mu_lock(&pollset->pollable.po.mu); + gpr_mu_lock(&worker->pollable->po.mu); + } + *now = gpr_now(now->clock_type); + } + + return do_poll && pollset->shutdown_closure == NULL && + pollset->current_pollable == worker->pollable; +} + +static void end_worker(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_pollset_worker *worker, + grpc_pollset_worker **worker_hdl) { + if (NEW_ROOT == + worker_remove(&worker->pollable->root_worker, PWL_POLLABLE, worker)) { + gpr_cv_signal(&worker->pollable->root_worker->cv); + } + if (worker->initialized_cv) { + gpr_cv_destroy(&worker->cv); + } + if (pollset_is_pollable_fd(pollset, worker->pollable)) { + UNREF_BY(exec_ctx, (grpc_fd *)worker->pollable, 2, "one_poll"); + } + if (EMPTIED == worker_remove(&pollset->root_worker, PWL_POLLSET, worker)) { + pollset_maybe_finish_shutdown(exec_ctx, pollset); + } +} + +/* pollset->po.mu lock must be held by the caller before calling this. + The function pollset_work() may temporarily release the lock (pollset->po.mu) + during the course of its execution but it will always re-acquire the lock and + ensure that it is held by the time the function returns */ +static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_pollset_worker **worker_hdl, + gpr_timespec now, gpr_timespec deadline) { + grpc_pollset_worker worker; + if (0 && GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "PS:%p work hdl=%p worker=%p now=%" PRId64 + ".%09d deadline=%" PRId64 ".%09d kwp=%d root_worker=%p", + pollset, worker_hdl, &worker, now.tv_sec, now.tv_nsec, + deadline.tv_sec, deadline.tv_nsec, pollset->kicked_without_poller, + pollset->root_worker); + } + grpc_error *error = GRPC_ERROR_NONE; + static const char *err_desc = "pollset_work"; + if (pollset->kicked_without_poller) { + pollset->kicked_without_poller = false; + return GRPC_ERROR_NONE; + } + if (pollset->current_pollable != &pollset->pollable) { + gpr_mu_lock(&pollset->current_pollable->po.mu); + } + if (begin_worker(pollset, &worker, worker_hdl, &now, deadline)) { + gpr_tls_set(&g_current_thread_pollset, (intptr_t)pollset); + gpr_tls_set(&g_current_thread_worker, (intptr_t)&worker); + GPR_ASSERT(!pollset->shutdown_closure); + append_error(&error, pollable_materialize(worker.pollable), err_desc); + if (worker.pollable != &pollset->pollable) { + gpr_mu_unlock(&worker.pollable->po.mu); + } + gpr_mu_unlock(&pollset->pollable.po.mu); + append_error(&error, pollset_epoll(exec_ctx, pollset, worker.pollable, now, + deadline), + err_desc); + grpc_exec_ctx_flush(exec_ctx); + gpr_mu_lock(&pollset->pollable.po.mu); + if (worker.pollable != &pollset->pollable) { + gpr_mu_lock(&worker.pollable->po.mu); + } + gpr_tls_set(&g_current_thread_pollset, 0); + gpr_tls_set(&g_current_thread_worker, 0); + pollset_maybe_finish_shutdown(exec_ctx, pollset); + } + end_worker(exec_ctx, pollset, &worker, worker_hdl); + if (worker.pollable != &pollset->pollable) { + gpr_mu_unlock(&worker.pollable->po.mu); + } + return error; +} + +static void unref_fd_no_longer_poller(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_fd *fd = arg; + UNREF_BY(exec_ctx, fd, 2, "pollset_pollable"); +} + +/* expects pollsets locked, flag whether fd is locked or not */ +static grpc_error *pollset_add_fd_locked(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset, grpc_fd *fd, + bool fd_locked) { + static const char *err_desc = "pollset_add_fd"; + grpc_error *error = GRPC_ERROR_NONE; + if (pollset->current_pollable == &g_empty_pollable) { + if (GRPC_TRACER_ON(grpc_polling_trace)) + gpr_log(GPR_DEBUG, + "PS:%p add fd %p; transition pollable from empty to fd", pollset, + fd); + /* empty pollable --> single fd pollable */ + append_error(&error, pollset_kick_all(pollset), err_desc); + pollset->current_pollable = &fd->pollable; + if (!fd_locked) gpr_mu_lock(&fd->pollable.po.mu); + append_error(&error, fd_become_pollable_locked(fd), err_desc); + if (!fd_locked) gpr_mu_unlock(&fd->pollable.po.mu); + REF_BY(fd, 2, "pollset_pollable"); + } else if (pollset->current_pollable == &pollset->pollable) { + if (GRPC_TRACER_ON(grpc_polling_trace)) + gpr_log(GPR_DEBUG, "PS:%p add fd %p; already multipolling", pollset, fd); + append_error(&error, pollable_add_fd(pollset->current_pollable, fd), + err_desc); + } else if (pollset->current_pollable != &fd->pollable) { + grpc_fd *had_fd = (grpc_fd *)pollset->current_pollable; + if (GRPC_TRACER_ON(grpc_polling_trace)) + gpr_log(GPR_DEBUG, + "PS:%p add fd %p; transition pollable from fd %p to multipoller", + pollset, fd, had_fd); + append_error(&error, pollset_kick_all(pollset), err_desc); + pollset->current_pollable = &pollset->pollable; + if (append_error(&error, pollable_materialize(&pollset->pollable), + err_desc)) { + pollable_add_fd(&pollset->pollable, had_fd); + pollable_add_fd(&pollset->pollable, fd); + } + grpc_closure_sched(exec_ctx, + grpc_closure_create(unref_fd_no_longer_poller, had_fd, + grpc_schedule_on_exec_ctx), + GRPC_ERROR_NONE); + } + return error; +} + +static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, + grpc_fd *fd) { + gpr_mu_lock(&pollset->pollable.po.mu); + grpc_error *error = pollset_add_fd_locked(exec_ctx, pollset, fd, false); + gpr_mu_unlock(&pollset->pollable.po.mu); + GRPC_LOG_IF_ERROR("pollset_add_fd", error); +} + +/******************************************************************************* + * Pollset-set Definitions + */ + +static grpc_pollset_set *pollset_set_create(void) { + grpc_pollset_set *pss = gpr_zalloc(sizeof(*pss)); + po_init(&pss->po, PO_POLLSET_SET); + return pss; +} + +static void pollset_set_destroy(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss) { + po_destroy(&pss->po); + gpr_free(pss); +} + +static void pollset_set_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) { + po_join(exec_ctx, &pss->po, &fd->pollable.po); +} + +static void pollset_set_del_fd(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pss, + grpc_fd *fd) {} + +static void pollset_set_add_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) { + po_join(exec_ctx, &pss->po, &ps->pollable.po); +} + +static void pollset_set_del_pollset(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *pss, grpc_pollset *ps) {} + +static void pollset_set_add_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) { + po_join(exec_ctx, &bag->po, &item->po); +} + +static void pollset_set_del_pollset_set(grpc_exec_ctx *exec_ctx, + grpc_pollset_set *bag, + grpc_pollset_set *item) {} + +static void po_init(polling_obj *po, polling_obj_type type) { + gpr_mu_init(&po->mu); + po->type = type; + po->group = NULL; + po->next = po; + po->prev = po; +} + +static polling_group *pg_lock_latest(polling_group *pg) { + /* assumes pg unlocked; consumes ref, returns ref */ + gpr_mu_lock(&pg->po.mu); + while (pg->po.group != NULL) { + polling_group *new_pg = pg_ref(pg->po.group); + gpr_mu_unlock(&pg->po.mu); + pg_unref(pg); + pg = new_pg; + gpr_mu_lock(&pg->po.mu); + } + return pg; +} + +static void po_destroy(polling_obj *po) { + if (po->group != NULL) { + polling_group *pg = pg_lock_latest(po->group); + po->prev->next = po->next; + po->next->prev = po->prev; + gpr_mu_unlock(&pg->po.mu); + pg_unref(pg); + } + gpr_mu_destroy(&po->mu); +} + +static polling_group *pg_ref(polling_group *pg) { + gpr_ref(&pg->refs); + return pg; +} + +static void pg_unref(polling_group *pg) { + if (gpr_unref(&pg->refs)) { + po_destroy(&pg->po); + gpr_free(pg); + } +} + +static int po_cmp(polling_obj *a, polling_obj *b) { + if (a == b) return 0; + if (a->type < b->type) return -1; + if (a->type > b->type) return 1; + if (a < b) return -1; + assert(a > b); + return 1; +} + +static void po_join(grpc_exec_ctx *exec_ctx, polling_obj *a, polling_obj *b) { + switch (po_cmp(a, b)) { + case 0: + return; + case 1: + GPR_SWAP(polling_obj *, a, b); + /* fall through */ + case -1: + gpr_mu_lock(&a->mu); + gpr_mu_lock(&b->mu); + + if (a->group == NULL) { + if (b->group == NULL) { + polling_obj *initial_po[] = {a, b}; + pg_create(exec_ctx, initial_po, GPR_ARRAY_SIZE(initial_po)); + gpr_mu_unlock(&a->mu); + gpr_mu_unlock(&b->mu); + } else { + polling_group *b_group = pg_ref(b->group); + gpr_mu_unlock(&b->mu); + gpr_mu_unlock(&a->mu); + pg_join(exec_ctx, b_group, a); + } + } else if (b->group == NULL) { + polling_group *a_group = pg_ref(a->group); + gpr_mu_unlock(&a->mu); + gpr_mu_unlock(&b->mu); + pg_join(exec_ctx, a_group, b); + } else if (a->group == b->group) { + /* nothing to do */ + gpr_mu_unlock(&a->mu); + gpr_mu_unlock(&b->mu); + } else { + polling_group *a_group = pg_ref(a->group); + polling_group *b_group = pg_ref(b->group); + gpr_mu_unlock(&a->mu); + gpr_mu_unlock(&b->mu); + pg_merge(exec_ctx, a_group, b_group); + } + } +} + +static void pg_notify(grpc_exec_ctx *exec_ctx, polling_obj *a, polling_obj *b) { + if (a->type == PO_FD && b->type == PO_POLLSET) { + pollset_add_fd_locked(exec_ctx, (grpc_pollset *)b, (grpc_fd *)a, true); + } else if (a->type == PO_POLLSET && b->type == PO_FD) { + pollset_add_fd_locked(exec_ctx, (grpc_pollset *)a, (grpc_fd *)b, true); + } +} + +static void pg_broadcast(grpc_exec_ctx *exec_ctx, polling_group *from, + polling_group *to) { + for (polling_obj *a = from->po.next; a != &from->po; a = a->next) { + for (polling_obj *b = to->po.next; b != &to->po; b = b->next) { + if (po_cmp(a, b) < 0) { + gpr_mu_lock(&a->mu); + gpr_mu_lock(&b->mu); + } else { + GPR_ASSERT(po_cmp(a, b) != 0); + gpr_mu_lock(&b->mu); + gpr_mu_lock(&a->mu); + } + pg_notify(exec_ctx, a, b); + gpr_mu_unlock(&a->mu); + gpr_mu_unlock(&b->mu); + } + } +} + +static void pg_create(grpc_exec_ctx *exec_ctx, polling_obj **initial_po, + size_t initial_po_count) { + /* assumes all polling objects in initial_po are locked */ + polling_group *pg = gpr_malloc(sizeof(*pg)); + po_init(&pg->po, PO_POLLING_GROUP); + gpr_ref_init(&pg->refs, (int)initial_po_count); + for (size_t i = 0; i < initial_po_count; i++) { + GPR_ASSERT(initial_po[i]->group == NULL); + initial_po[i]->group = pg; + } + for (size_t i = 1; i < initial_po_count; i++) { + initial_po[i]->prev = initial_po[i - 1]; + } + for (size_t i = 0; i < initial_po_count - 1; i++) { + initial_po[i]->next = initial_po[i + 1]; + } + initial_po[0]->prev = &pg->po; + initial_po[initial_po_count - 1]->next = &pg->po; + pg->po.next = initial_po[0]; + pg->po.prev = initial_po[initial_po_count - 1]; + for (size_t i = 1; i < initial_po_count; i++) { + for (size_t j = 0; j < i; j++) { + pg_notify(exec_ctx, initial_po[i], initial_po[j]); + } + } +} + +static void pg_join(grpc_exec_ctx *exec_ctx, polling_group *pg, + polling_obj *po) { + /* assumes neither pg nor po are locked; consumes one ref to pg */ + pg = pg_lock_latest(pg); + /* pg locked */ + for (polling_obj *existing = pg->po.next /* skip pg - it's just a stub */; + existing != &pg->po; existing = existing->next) { + if (po_cmp(po, existing) < 0) { + gpr_mu_lock(&po->mu); + gpr_mu_lock(&existing->mu); + } else { + GPR_ASSERT(po_cmp(po, existing) != 0); + gpr_mu_lock(&existing->mu); + gpr_mu_lock(&po->mu); + } + /* pg, po, existing locked */ + if (po->group != NULL) { + gpr_mu_unlock(&pg->po.mu); + polling_group *po_group = pg_ref(po->group); + gpr_mu_unlock(&po->mu); + gpr_mu_unlock(&existing->mu); + pg_merge(exec_ctx, pg, po_group); + /* early exit: polling obj picked up a group during joining: we needed + to do a full merge */ + return; + } + pg_notify(exec_ctx, po, existing); + gpr_mu_unlock(&po->mu); + gpr_mu_unlock(&existing->mu); + } + gpr_mu_lock(&po->mu); + if (po->group != NULL) { + gpr_mu_unlock(&pg->po.mu); + polling_group *po_group = pg_ref(po->group); + gpr_mu_unlock(&po->mu); + pg_merge(exec_ctx, pg, po_group); + /* early exit: polling obj picked up a group during joining: we needed + to do a full merge */ + return; + } + po->group = pg; + po->next = &pg->po; + po->prev = pg->po.prev; + po->prev->next = po->next->prev = po; + gpr_mu_unlock(&pg->po.mu); + gpr_mu_unlock(&po->mu); +} + +static void pg_merge(grpc_exec_ctx *exec_ctx, polling_group *a, + polling_group *b) { + for (;;) { + if (a == b) { + pg_unref(a); + pg_unref(b); + return; + } + if (a > b) GPR_SWAP(polling_group *, a, b); + gpr_mu_lock(&a->po.mu); + gpr_mu_lock(&b->po.mu); + if (a->po.group != NULL) { + polling_group *m2 = pg_ref(a->po.group); + gpr_mu_unlock(&a->po.mu); + gpr_mu_unlock(&b->po.mu); + pg_unref(a); + a = m2; + } else if (b->po.group != NULL) { + polling_group *m2 = pg_ref(b->po.group); + gpr_mu_unlock(&a->po.mu); + gpr_mu_unlock(&b->po.mu); + pg_unref(b); + b = m2; + } else { + break; + } + } + polling_group **unref = NULL; + size_t unref_count = 0; + size_t unref_cap = 0; + b->po.group = a; + pg_broadcast(exec_ctx, a, b); + pg_broadcast(exec_ctx, b, a); + while (b->po.next != &b->po) { + polling_obj *po = b->po.next; + gpr_mu_lock(&po->mu); + if (unref_count == unref_cap) { + unref_cap = GPR_MAX(8, 3 * unref_cap / 2); + unref = gpr_realloc(unref, unref_cap * sizeof(*unref)); + } + unref[unref_count++] = po->group; + po->group = pg_ref(a); + // unlink from b + po->prev->next = po->next; + po->next->prev = po->prev; + // link to a + po->next = &a->po; + po->prev = a->po.prev; + po->next->prev = po->prev->next = po; + gpr_mu_unlock(&po->mu); + } + gpr_mu_unlock(&a->po.mu); + gpr_mu_unlock(&b->po.mu); + for (size_t i = 0; i < unref_count; i++) { + pg_unref(unref[i]); + } + gpr_free(unref); + pg_unref(b); +} + +/******************************************************************************* + * Event engine binding + */ + +static void shutdown_engine(void) { + fd_global_shutdown(); + pollset_global_shutdown(); +} + +static const grpc_event_engine_vtable vtable = { + .pollset_size = sizeof(grpc_pollset), + + .fd_create = fd_create, + .fd_wrapped_fd = fd_wrapped_fd, + .fd_orphan = fd_orphan, + .fd_shutdown = fd_shutdown, + .fd_is_shutdown = fd_is_shutdown, + .fd_notify_on_read = fd_notify_on_read, + .fd_notify_on_write = fd_notify_on_write, + .fd_get_read_notifier_pollset = fd_get_read_notifier_pollset, + .fd_get_workqueue = fd_get_workqueue, + + .pollset_init = pollset_init, + .pollset_shutdown = pollset_shutdown, + .pollset_destroy = pollset_destroy, + .pollset_work = pollset_work, + .pollset_kick = pollset_kick, + .pollset_add_fd = pollset_add_fd, + + .pollset_set_create = pollset_set_create, + .pollset_set_destroy = pollset_set_destroy, + .pollset_set_add_pollset = pollset_set_add_pollset, + .pollset_set_del_pollset = pollset_set_del_pollset, + .pollset_set_add_pollset_set = pollset_set_add_pollset_set, + .pollset_set_del_pollset_set = pollset_set_del_pollset_set, + .pollset_set_add_fd = pollset_set_add_fd, + .pollset_set_del_fd = pollset_set_del_fd, + + .workqueue_ref = workqueue_ref, + .workqueue_unref = workqueue_unref, + .workqueue_scheduler = workqueue_scheduler, + + .shutdown_engine = shutdown_engine, +}; + +const grpc_event_engine_vtable *grpc_init_epollex_linux( + bool explicitly_requested) { + if (!explicitly_requested) return NULL; + + if (!grpc_has_wakeup_fd()) { + return NULL; + } + + if (!grpc_is_epollexclusive_available()) { + return NULL; + } + + fd_global_init(); + + if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { + pollset_global_shutdown(); + fd_global_shutdown(); + return NULL; + } + + return &vtable; +} + +#else /* defined(GRPC_LINUX_EPOLL) */ +#if defined(GRPC_POSIX_SOCKET) +#include "src/core/lib/iomgr/ev_posix.h" +/* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return + * NULL */ +const grpc_event_engine_vtable *grpc_init_epollex_linux( + bool explicitly_requested) { + return NULL; +} +#endif /* defined(GRPC_POSIX_SOCKET) */ + +#endif /* !defined(GRPC_LINUX_EPOLL) */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.h b/src/core/lib/iomgr/ev_epollex_linux.h new file mode 100644 index 0000000000000000000000000000000000000000..a078a7f19a82635beb57b7efc083e0ffa039fdd5 --- /dev/null +++ b/src/core/lib/iomgr/ev_epollex_linux.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLLEX_LINUX_H +#define GRPC_CORE_LIB_IOMGR_EV_EPOLLEX_LINUX_H + +#include "src/core/lib/iomgr/ev_posix.h" +#include "src/core/lib/iomgr/port.h" + +const grpc_event_engine_vtable *grpc_init_epollex_linux( + bool explicitly_requested); + +#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLLEX_LINUX_H */ diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epollsig_linux.c similarity index 97% rename from src/core/lib/iomgr/ev_epoll_linux.c rename to src/core/lib/iomgr/ev_epollsig_linux.c index e603a755937286e80ab1d8d14cd51be6c3a9287e..52362a62f47f047367c43dcc1b21a3efd3f52891 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epollsig_linux.c @@ -36,7 +36,7 @@ /* This polling engine is only relevant on linux kernels supporting epoll() */ #ifdef GRPC_LINUX_EPOLL -#include "src/core/lib/iomgr/ev_epoll_linux.h" +#include "src/core/lib/iomgr/ev_epollsig_linux.h" #include <assert.h> #include <errno.h> @@ -63,11 +63,11 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/block_annotate.h" -/* TODO: sreek - Move this to init.c and initialize this like other tracers. */ -static int grpc_polling_trace = 0; /* Disabled by default */ -#define GRPC_POLLING_TRACE(fmt, ...) \ - if (grpc_polling_trace) { \ - gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \ +#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) + +#define GRPC_POLLING_TRACE(fmt, ...) \ + if (GRPC_TRACER_ON(grpc_polling_trace)) { \ + gpr_log(GPR_INFO, (fmt), __VA_ARGS__); \ } /* Uncomment the following to enable extra checks on poll_object operations */ @@ -76,11 +76,6 @@ static int grpc_polling_trace = 0; /* Disabled by default */ static int grpc_wakeup_signal = -1; static bool is_grpc_wakeup_signal_initialized = false; -/* TODO: sreek: Right now, this wakes up all pollers. In future we should make - * sure to wake up one polling thread (which can wake up other threads if - * needed) */ -static grpc_wakeup_fd global_wakeup_fd; - /* Implements the function defined in grpc_posix.h. This function might be * called before even calling grpc_init() to set either a different signal to * use. If signum == -1, then the use of signals is disabled */ @@ -454,8 +449,8 @@ static void polling_island_add_wakeup_fd_locked(polling_island *pi, gpr_asprintf(&err_msg, "epoll_ctl (epoll_fd: %d) add wakeup fd: %d failed with " "error: %d (%s)", - pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(&global_wakeup_fd), - errno, strerror(errno)); + pi->epoll_fd, GRPC_WAKEUP_FD_GET_READ_FD(wakeup_fd), errno, + strerror(errno)); append_error(error, GRPC_OS_ERROR(errno, err_msg), err_desc); gpr_free(err_msg); } @@ -558,7 +553,6 @@ static polling_island *polling_island_create(grpc_exec_ctx *exec_ctx, goto done; } - polling_island_add_wakeup_fd_locked(pi, &global_wakeup_fd, error); polling_island_add_wakeup_fd_locked(pi, &pi->workqueue_wakeup_fd, error); if (initial_fd != NULL) { @@ -1116,11 +1110,10 @@ static grpc_error *pollset_global_init(void) { gpr_tls_init(&g_current_thread_pollset); gpr_tls_init(&g_current_thread_worker); poller_kick_init(); - return grpc_wakeup_fd_init(&global_wakeup_fd); + return GRPC_ERROR_NONE; } static void pollset_global_shutdown(void) { - grpc_wakeup_fd_destroy(&global_wakeup_fd); gpr_tls_destroy(&g_current_thread_pollset); gpr_tls_destroy(&g_current_thread_worker); } @@ -1226,10 +1219,6 @@ static grpc_error *pollset_kick(grpc_pollset *p, return error; } -static grpc_error *kick_poller(void) { - return grpc_wakeup_fd_wakeup(&global_wakeup_fd); -} - static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { gpr_mu_init(&pollset->po.mu); *mu = &pollset->po.mu; @@ -1332,7 +1321,7 @@ static void pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, /* pollset_shutdown is guaranteed to be called before pollset_destroy. So other * than destroying the mutexes, there is nothing special that needs to be done * here */ -static void pollset_destroy(grpc_pollset *pollset) { +static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { GPR_ASSERT(!pollset_has_workers(pollset)); gpr_mu_destroy(&pollset->po.mu); } @@ -1453,11 +1442,7 @@ static void pollset_work_and_unlock(grpc_exec_ctx *exec_ctx, for (int i = 0; i < ep_rv; ++i) { void *data_ptr = ep_ev[i].data.ptr; - if (data_ptr == &global_wakeup_fd) { - grpc_timer_consume_kick(); - append_error(error, grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd), - err_desc); - } else if (data_ptr == &pi->workqueue_wakeup_fd) { + if (data_ptr == &pi->workqueue_wakeup_fd) { append_error(error, grpc_wakeup_fd_consume_wakeup(&pi->workqueue_wakeup_fd), err_desc); @@ -1897,8 +1882,6 @@ static const grpc_event_engine_vtable vtable = { .pollset_set_add_fd = pollset_set_add_fd, .pollset_set_del_fd = pollset_set_del_fd, - .kick_poller = kick_poller, - .workqueue_ref = workqueue_ref, .workqueue_unref = workqueue_unref, .workqueue_scheduler = workqueue_scheduler, @@ -1921,7 +1904,8 @@ static bool is_epoll_available() { return true; } -const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { +const grpc_event_engine_vtable *grpc_init_epollsig_linux( + bool explicit_request) { /* If use of signals is disabled, we cannot use epoll engine*/ if (is_grpc_wakeup_signal_initialized && grpc_wakeup_signal < 0) { return NULL; @@ -1936,7 +1920,13 @@ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { } if (!is_grpc_wakeup_signal_initialized) { - grpc_use_signal(SIGRTMIN + 6); + /* TODO(ctiller): when other epoll engines are ready, remove the true || to + * force this to be explitly chosen if needed */ + if (true || explicit_request) { + grpc_use_signal(SIGRTMIN + 6); + } else { + return NULL; + } } fd_global_init(); @@ -1958,7 +1948,10 @@ const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { #include "src/core/lib/iomgr/ev_posix.h" /* If GRPC_LINUX_EPOLL is not defined, it means epoll is not available. Return * NULL */ -const grpc_event_engine_vtable *grpc_init_epoll_linux(void) { return NULL; } +const grpc_event_engine_vtable *grpc_init_epollsig_linux( + bool explicit_request) { + return NULL; +} #endif /* defined(GRPC_POSIX_SOCKET) */ void grpc_use_signal(int signum) {} diff --git a/src/core/lib/iomgr/ev_epoll_linux.h b/src/core/lib/iomgr/ev_epollsig_linux.h similarity index 89% rename from src/core/lib/iomgr/ev_epoll_linux.h rename to src/core/lib/iomgr/ev_epollsig_linux.h index 8fc3ff59a3ed044ae6d7322907da780aa4313a3f..9e4034f2a7f9f2bba24454665b192f098d07bdf8 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.h +++ b/src/core/lib/iomgr/ev_epollsig_linux.h @@ -31,13 +31,13 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLL_LINUX_H -#define GRPC_CORE_LIB_IOMGR_EV_EPOLL_LINUX_H +#ifndef GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H +#define GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/port.h" -const grpc_event_engine_vtable *grpc_init_epoll_linux(void); +const grpc_event_engine_vtable *grpc_init_epollsig_linux(bool explicit_request); #ifdef GRPC_LINUX_EPOLL void *grpc_fd_get_polling_island(grpc_fd *fd); @@ -45,4 +45,4 @@ void *grpc_pollset_get_polling_island(grpc_pollset *ps); bool grpc_are_polling_islands_equal(void *p, void *q); #endif /* defined(GRPC_LINUX_EPOLL) */ -#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLL_LINUX_H */ +#endif /* GRPC_CORE_LIB_IOMGR_EV_EPOLLSIG_LINUX_H */ diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index 9834cdd197963df9a92f1176297842f0bc700957..3a7648ac3296e8d92940fb373b212a801e586535 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -58,6 +58,8 @@ #include "src/core/lib/profiling/timers.h" #include "src/core/lib/support/block_annotate.h" +#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) + /******************************************************************************* * FD declarations */ @@ -122,8 +124,6 @@ struct grpc_fd { grpc_pollset *read_notifier_pollset; }; -static grpc_wakeup_fd global_wakeup_fd; - /* Begin polling on an fd. Registers that the given pollset is interested in this fd - so that if read or writability interest changes, the pollset can be kicked to pick up that @@ -784,19 +784,14 @@ static grpc_error *pollset_kick(grpc_pollset *p, static grpc_error *pollset_global_init(void) { gpr_tls_init(&g_current_thread_poller); gpr_tls_init(&g_current_thread_worker); - return grpc_wakeup_fd_init(&global_wakeup_fd); + return GRPC_ERROR_NONE; } static void pollset_global_shutdown(void) { - grpc_wakeup_fd_destroy(&global_wakeup_fd); gpr_tls_destroy(&g_current_thread_poller); gpr_tls_destroy(&g_current_thread_worker); } -static grpc_error *kick_poller(void) { - return grpc_wakeup_fd_wakeup(&global_wakeup_fd); -} - /* main interface */ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { @@ -815,7 +810,7 @@ static void pollset_init(grpc_pollset *pollset, gpr_mu **mu) { pollset->pollset_set_count = 0; } -static void pollset_destroy(grpc_pollset *pollset) { +static void pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { GPR_ASSERT(!pollset_has_workers(pollset)); GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); while (pollset->local_wakeup_cache) { @@ -952,13 +947,10 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, } fd_count = 0; - pfd_count = 2; - pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&global_wakeup_fd); + pfd_count = 1; + pfds[0].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker.wakeup_fd->fd); pfds[0].events = POLLIN; pfds[0].revents = 0; - pfds[1].fd = GRPC_WAKEUP_FD_GET_READ_FD(&worker.wakeup_fd->fd); - pfds[1].events = POLLIN; - pfds[1].revents = 0; for (i = 0; i < pollset->fd_count; i++) { if (fd_is_orphaned(pollset->fds[i])) { GRPC_FD_UNREF(pollset->fds[i], "multipoller"); @@ -974,7 +966,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, pollset->fd_count = fd_count; gpr_mu_unlock(&pollset->mu); - for (i = 2; i < pfd_count; i++) { + for (i = 1; i < pfd_count; i++) { grpc_fd *fd = watchers[i].fd; pfds[i].events = (short)fd_begin_poll(fd, pollset, &worker, POLLIN, POLLOUT, &watchers[i]); @@ -992,7 +984,7 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, work_combine_error(&error, GRPC_OS_ERROR(errno, "poll")); } - for (i = 2; i < pfd_count; i++) { + for (i = 1; i < pfd_count; i++) { if (watchers[i].fd == NULL) { fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); } else { @@ -1002,20 +994,15 @@ static grpc_error *pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, } } } else if (r == 0) { - for (i = 2; i < pfd_count; i++) { + for (i = 1; i < pfd_count; i++) { fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); } } else { if (pfds[0].revents & POLLIN_CHECK) { - grpc_timer_consume_kick(); - work_combine_error(&error, - grpc_wakeup_fd_consume_wakeup(&global_wakeup_fd)); - } - if (pfds[1].revents & POLLIN_CHECK) { work_combine_error( &error, grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd)); } - for (i = 2; i < pfd_count; i++) { + for (i = 1; i < pfd_count; i++) { if (watchers[i].fd == NULL) { fd_end_poll(exec_ctx, &watchers[i], 0, 0, NULL); } else { @@ -1560,8 +1547,6 @@ static const grpc_event_engine_vtable vtable = { .pollset_set_add_fd = pollset_set_add_fd, .pollset_set_del_fd = pollset_set_del_fd, - .kick_poller = kick_poller, - .workqueue_ref = workqueue_ref, .workqueue_unref = workqueue_unref, .workqueue_scheduler = workqueue_scheduler, @@ -1569,7 +1554,7 @@ static const grpc_event_engine_vtable vtable = { .shutdown_engine = shutdown_engine, }; -const grpc_event_engine_vtable *grpc_init_poll_posix(void) { +const grpc_event_engine_vtable *grpc_init_poll_posix(bool explicit_request) { if (!grpc_has_wakeup_fd()) { return NULL; } @@ -1579,7 +1564,7 @@ const grpc_event_engine_vtable *grpc_init_poll_posix(void) { return &vtable; } -const grpc_event_engine_vtable *grpc_init_poll_cv_posix(void) { +const grpc_event_engine_vtable *grpc_init_poll_cv_posix(bool explicit_request) { global_cv_fd_table_init(); grpc_enable_cv_wakeup_fds(1); if (!GRPC_LOG_IF_ERROR("pollset_global_init", pollset_global_init())) { diff --git a/src/core/lib/iomgr/ev_poll_posix.h b/src/core/lib/iomgr/ev_poll_posix.h index 202ffca14ca750293e6df9b4a2cdeca5a9332be1..2890e93eadea6f43468d4ab6cb6caee738bb9602 100644 --- a/src/core/lib/iomgr/ev_poll_posix.h +++ b/src/core/lib/iomgr/ev_poll_posix.h @@ -36,7 +36,7 @@ #include "src/core/lib/iomgr/ev_posix.h" -const grpc_event_engine_vtable *grpc_init_poll_posix(void); -const grpc_event_engine_vtable *grpc_init_poll_cv_posix(void); +const grpc_event_engine_vtable *grpc_init_poll_posix(bool explicit_request); +const grpc_event_engine_vtable *grpc_init_poll_cv_posix(bool explicit_request); #endif /* GRPC_CORE_LIB_IOMGR_EV_POLL_POSIX_H */ diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 13409a4de83edd1d6efcd28c7d9bf6db6e09cc10..c4d2f23e291115cca2b0ba75ef66be66f83f9bf3 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -44,10 +44,18 @@ #include <grpc/support/string_util.h> #include <grpc/support/useful.h> -#include "src/core/lib/iomgr/ev_epoll_linux.h" +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/iomgr/ev_epoll1_linux.h" +#include "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h" +#include "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h" +#include "src/core/lib/iomgr/ev_epollex_linux.h" +#include "src/core/lib/iomgr/ev_epollsig_linux.h" #include "src/core/lib/iomgr/ev_poll_posix.h" #include "src/core/lib/support/env.h" +grpc_tracer_flag grpc_polling_trace = + GRPC_TRACER_INITIALIZER(false); /* Disabled by default */ + /** Default poll() function - a pointer so that it can be overridden by some * tests */ grpc_poll_function_type grpc_poll_function = poll; @@ -57,7 +65,8 @@ grpc_wakeup_fd grpc_global_wakeup_fd; static const grpc_event_engine_vtable *g_event_engine; static const char *g_poll_strategy_name = NULL; -typedef const grpc_event_engine_vtable *(*event_engine_factory_fn)(void); +typedef const grpc_event_engine_vtable *(*event_engine_factory_fn)( + bool explicit_request); typedef struct { const char *name; @@ -65,7 +74,11 @@ typedef struct { } event_engine_factory; static const event_engine_factory g_factories[] = { - {"epoll", grpc_init_epoll_linux}, + {"epollex", grpc_init_epollex_linux}, + {"epollsig", grpc_init_epollsig_linux}, + {"epoll1", grpc_init_epoll1_linux}, + {"epoll-threadpool", grpc_init_epoll_thread_pool_linux}, + {"epoll-limited", grpc_init_epoll_limited_pollers_linux}, {"poll", grpc_init_poll_posix}, {"poll-cv", grpc_init_poll_cv_posix}, }; @@ -102,7 +115,8 @@ static bool is(const char *want, const char *have) { static void try_engine(const char *engine) { for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) { if (is(engine, g_factories[i].name)) { - if ((g_event_engine = g_factories[i].factory())) { + if ((g_event_engine = g_factories[i].factory( + 0 == strcmp(engine, g_factories[i].name)))) { g_poll_strategy_name = g_factories[i].name; gpr_log(GPR_DEBUG, "Using polling engine: %s", g_factories[i].name); return; @@ -121,6 +135,8 @@ void grpc_set_event_engine_test_only( const char *grpc_get_poll_strategy_name() { return g_poll_strategy_name; } void grpc_event_engine_init(void) { + grpc_register_tracer("polling", &grpc_polling_trace); + char *s = gpr_getenv("GRPC_POLL_STRATEGY"); if (s == NULL) { s = gpr_strdup("all"); @@ -197,8 +213,8 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, g_event_engine->pollset_shutdown(exec_ctx, pollset, closure); } -void grpc_pollset_destroy(grpc_pollset *pollset) { - g_event_engine->pollset_destroy(pollset); +void grpc_pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { + g_event_engine->pollset_destroy(exec_ctx, pollset); } grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, @@ -260,8 +276,6 @@ void grpc_pollset_set_del_fd(grpc_exec_ctx *exec_ctx, g_event_engine->pollset_set_del_fd(exec_ctx, pollset_set, fd); } -grpc_error *grpc_kick_poller(void) { return g_event_engine->kick_poller(); } - #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG grpc_workqueue *grpc_workqueue_ref(grpc_workqueue *workqueue, const char *file, int line, const char *reason) { diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index becc4d359e52ad67479ac83791b7170e1d069eef..80619aab5fcaea9074424d17bfd16abf5cf3a960 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -36,12 +36,15 @@ #include <poll.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/iomgr/workqueue.h" +extern grpc_tracer_flag grpc_polling_trace; /* Disabled by default */ + typedef struct grpc_fd grpc_fd; typedef struct grpc_event_engine_vtable { @@ -64,7 +67,7 @@ typedef struct grpc_event_engine_vtable { void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu); void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); - void (*pollset_destroy)(grpc_pollset *pollset); + void (*pollset_destroy)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset); grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker, gpr_timespec now, gpr_timespec deadline); @@ -93,8 +96,6 @@ typedef struct grpc_event_engine_vtable { void (*pollset_set_del_fd)(grpc_exec_ctx *exec_ctx, grpc_pollset_set *pollset_set, grpc_fd *fd); - grpc_error *(*kick_poller)(void); - void (*shutdown_engine)(void); #ifdef GRPC_WORKQUEUE_REFCOUNT_DEBUG diff --git a/src/core/lib/iomgr/exec_ctx.c b/src/core/lib/iomgr/exec_ctx.c index 2532a708e7b0ba9aa0f6caec3ddf90c18c3d3d12..318bb2b7133837fdd0fc19857e3fd1926ebd2f00 100644 --- a/src/core/lib/iomgr/exec_ctx.c +++ b/src/core/lib/iomgr/exec_ctx.c @@ -62,6 +62,11 @@ bool grpc_always_ready_to_finish(grpc_exec_ctx *exec_ctx, void *arg_ignored) { return true; } +bool grpc_exec_ctx_has_work(grpc_exec_ctx *exec_ctx) { + return exec_ctx->active_combiner != NULL || + !grpc_closure_list_empty(exec_ctx->closure_list); +} + bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { bool did_something = 0; GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0); diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index f99a0fee5fc1f03bdfcb42aab6bf5112cb3ea267..759a3ae2d56faff71840b2d33f7c8f83b769451d 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -93,6 +93,8 @@ struct grpc_exec_ctx { extern grpc_closure_scheduler *grpc_schedule_on_exec_ctx; +bool grpc_exec_ctx_has_work(grpc_exec_ctx *exec_ctx); + /** Flush any work that has been enqueued onto this grpc_exec_ctx. * Caller must guarantee that no interfering locks are held. * Returns true if work was performed, false otherwise. */ diff --git a/src/core/lib/iomgr/iomgr.c b/src/core/lib/iomgr/iomgr.c index 001e528409978d562588e1cc2a2cba32294c5639..1fd41c2f880fb42d50995cda19fb7b041ec70343 100644 --- a/src/core/lib/iomgr/iomgr.c +++ b/src/core/lib/iomgr/iomgr.c @@ -47,6 +47,7 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/network_status_tracker.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/iomgr/timer_manager.h" #include "src/core/lib/support/env.h" #include "src/core/lib/support/string.h" @@ -67,6 +68,8 @@ void grpc_iomgr_init(void) { grpc_iomgr_platform_init(); } +void grpc_iomgr_start(void) { grpc_timer_manager_init(); } + static size_t count_objects(void) { grpc_iomgr_object *obj; size_t n = 0; @@ -88,6 +91,7 @@ void grpc_iomgr_shutdown(grpc_exec_ctx *exec_ctx) { gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); gpr_timespec last_warning_time = gpr_now(GPR_CLOCK_REALTIME); + grpc_timer_manager_shutdown(); grpc_iomgr_platform_flush(); gpr_mu_lock(&g_mu); diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h index 245a1e08aa2e3e705feadc0fbf25a2e2e11de71b..6e2e0236154ecab9c472b2d23115fb7a6a73af4c 100644 --- a/src/core/lib/iomgr/iomgr.h +++ b/src/core/lib/iomgr/iomgr.h @@ -40,6 +40,9 @@ /** Initializes the iomgr. */ void grpc_iomgr_init(void); +/** Starts any background threads for iomgr. */ +void grpc_iomgr_start(void); + /** Signals the intention to shutdown the iomgr. Expects to be able to flush * exec_ctx. */ void grpc_iomgr_shutdown(grpc_exec_ctx *exec_ctx); diff --git a/src/core/lib/iomgr/is_epollexclusive_available.c b/src/core/lib/iomgr/is_epollexclusive_available.c new file mode 100644 index 0000000000000000000000000000000000000000..34fcf313e5e8f69f985df77a6c47e86fe3f200f3 --- /dev/null +++ b/src/core/lib/iomgr/is_epollexclusive_available.c @@ -0,0 +1,116 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/port.h" + +#include "src/core/lib/iomgr/is_epollexclusive_available.h" + +#ifdef GRPC_LINUX_EPOLL + +#include <grpc/support/log.h> + +#include <errno.h> +#include <sys/eventfd.h> +#include <unistd.h> + +#include "src/core/lib/iomgr/sys_epoll_wrapper.h" + +/* This polling engine is only relevant on linux kernels supporting epoll() */ +bool grpc_is_epollexclusive_available(void) { + static bool logged_why_not = false; + + int fd = epoll_create1(EPOLL_CLOEXEC); + if (fd < 0) { + if (!logged_why_not) { + gpr_log(GPR_ERROR, + "epoll_create1 failed with error: %d. Not using epollex polling " + "engine.", + fd); + logged_why_not = true; + } + return false; + } + int evfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + if (evfd < 0) { + if (!logged_why_not) { + gpr_log(GPR_ERROR, + "eventfd failed with error: %d. Not using epollex polling " + "engine.", + fd); + logged_why_not = true; + } + close(fd); + return false; + } + struct epoll_event ev = { + /* choose events that should cause an error on + EPOLLEXCLUSIVE enabled kernels - specifically the combination of + EPOLLONESHOT and EPOLLEXCLUSIVE */ + .events = (uint32_t)(EPOLLET | EPOLLIN | EPOLLEXCLUSIVE | EPOLLONESHOT), + .data.ptr = NULL}; + if (epoll_ctl(fd, EPOLL_CTL_ADD, evfd, &ev) != 0) { + if (errno != EINVAL) { + if (!logged_why_not) { + gpr_log( + GPR_ERROR, + "epoll_ctl with EPOLLEXCLUSIVE | EPOLLONESHOT failed with error: " + "%d. Not using epollex polling engine.", + errno); + logged_why_not = true; + } + close(fd); + close(evfd); + return false; + } + } else { + if (!logged_why_not) { + gpr_log(GPR_ERROR, + "epoll_ctl with EPOLLEXCLUSIVE | EPOLLONESHOT succeeded. This is " + "evidence of no EPOLLEXCLUSIVE support. Not using " + "epollex polling engine."); + logged_why_not = true; + } + close(fd); + close(evfd); + return false; + } + close(evfd); + close(fd); + return true; +} + +#else + +bool grpc_is_epollexclusive_available(void) { return false; } + +#endif diff --git a/test/build/c++11.cc b/src/core/lib/iomgr/is_epollexclusive_available.h similarity index 85% rename from test/build/c++11.cc rename to src/core/lib/iomgr/is_epollexclusive_available.h index 4822a20e7f24e6e0265537776c436f652bc880f0..b65b819e740286f1ee12c74d44c6d1a0f01889fd 100644 --- a/test/build/c++11.cc +++ b/src/core/lib/iomgr/is_epollexclusive_available.h @@ -31,22 +31,11 @@ * */ -/* This is just a compilation test, to see if we have C++11. */ +#ifndef GRPC_CORE_LIB_IOMGR_IS_EPOLLEXCLUSIVE_AVAILABLE_H +#define GRPC_CORE_LIB_IOMGR_IS_EPOLLEXCLUSIVE_AVAILABLE_H -#include <stdlib.h> -#include <zlib.h> +#include <stdbool.h> -class Base { - public: - virtual void foo() = 0; -}; +bool grpc_is_epollexclusive_available(void); -class Foo final : public Base { - public: - void foo() override {} -}; - -int main() { - Foo().foo(); - return 0; -} +#endif /* GRPC_CORE_LIB_IOMGR_IS_EPOLLEXCLUSIVE_AVAILABLE_H */ diff --git a/src/core/lib/iomgr/lockfree_event.c b/src/core/lib/iomgr/lockfree_event.c index 17e3bbf7278ee6065d27674efb858dd040e5b065..898ec1cb1bf8d75b1f0650c9aa1c3c4c5620883f 100644 --- a/src/core/lib/iomgr/lockfree_event.c +++ b/src/core/lib/iomgr/lockfree_event.c @@ -35,6 +35,10 @@ #include <grpc/support/log.h> +#include "src/core/lib/debug/trace.h" + +extern grpc_tracer_flag grpc_polling_trace; + /* 'state' holds the to call when the fd is readable or writable respectively. It can contain one of the following values: CLOSURE_READY : The fd has an I/O event of interest but there is no @@ -93,6 +97,10 @@ void grpc_lfev_notify_on(grpc_exec_ctx *exec_ctx, gpr_atm *state, grpc_closure *closure) { while (true) { gpr_atm curr = gpr_atm_no_barrier_load(state); + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "lfev_notify_on: %p curr=%p closure=%p", state, + (void *)curr, closure); + } switch (curr) { case CLOSURE_NOT_READY: { /* CLOSURE_NOT_READY -> <closure>. @@ -155,6 +163,10 @@ bool grpc_lfev_set_shutdown(grpc_exec_ctx *exec_ctx, gpr_atm *state, while (true) { gpr_atm curr = gpr_atm_no_barrier_load(state); + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "lfev_set_shutdown: %p curr=%p err=%s", state, + (void *)curr, grpc_error_string(shutdown_err)); + } switch (curr) { case CLOSURE_READY: case CLOSURE_NOT_READY: @@ -200,6 +212,10 @@ void grpc_lfev_set_ready(grpc_exec_ctx *exec_ctx, gpr_atm *state) { while (true) { gpr_atm curr = gpr_atm_no_barrier_load(state); + if (GRPC_TRACER_ON(grpc_polling_trace)) { + gpr_log(GPR_DEBUG, "lfev_set_ready: %p curr=%p", state, (void *)curr); + } + switch (curr) { case CLOSURE_READY: { /* Already ready. We are done here */ diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h index 9bf3cdac89e2a4152964a904886f5aabdebdb514..69e20098d7095435ed43bb8e3ac6005b19acdc11 100644 --- a/src/core/lib/iomgr/pollset.h +++ b/src/core/lib/iomgr/pollset.h @@ -40,8 +40,6 @@ #include "src/core/lib/iomgr/exec_ctx.h" -#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) - /* A grpc_pollset is a set of file descriptors that a higher level item is interested in. For example: - a server will typically keep a pollset containing all connected channels, @@ -59,7 +57,7 @@ void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu); * pollset's mutex must be held */ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); -void grpc_pollset_destroy(grpc_pollset *pollset); +void grpc_pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset); /* Do some work on a pollset. May involve invoking asynchronous callbacks, or actually polling file @@ -88,8 +86,7 @@ grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, gpr_timespec deadline) GRPC_MUST_USE_RESULT; /* Break one polling thread out of polling work for this pollset. - If specific_worker is GRPC_POLLSET_KICK_BROADCAST, kick ALL the workers. - Otherwise, if specific_worker is non-NULL, then kick that worker. */ + If specific_worker is non-NULL, then kick that worker. */ grpc_error *grpc_pollset_kick(grpc_pollset *pollset, grpc_pollset_worker *specific_worker) GRPC_MUST_USE_RESULT; diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c index a2f81bcd78d6354c754088972c095187f9f2bce6..5923da98e278f066783d5d0431199b166096af21 100644 --- a/src/core/lib/iomgr/pollset_uv.c +++ b/src/core/lib/iomgr/pollset_uv.c @@ -106,7 +106,7 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE); } -void grpc_pollset_destroy(grpc_pollset *pollset) { +void grpc_pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) { uv_close((uv_handle_t *)&pollset->timer, timer_close_cb); // timer.data is a boolean indicating that the timer has finished closing pollset->timer.data = (void *)0; diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c index 04c6b7174759d10821a4ed510c185a8b80259a84..b5f454cfa9b63e8c1d5a1d12275aa128f936c51e 100644 --- a/src/core/lib/iomgr/pollset_windows.c +++ b/src/core/lib/iomgr/pollset_windows.c @@ -43,6 +43,8 @@ #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_windows.h" +#define GRPC_POLLSET_KICK_BROADCAST ((grpc_pollset_worker *)1) + gpr_mu grpc_polling_mu; static grpc_pollset_worker *g_active_poller; static grpc_pollset_worker g_global_root_worker; @@ -114,7 +116,7 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, } } -void grpc_pollset_destroy(grpc_pollset *pollset) {} +void grpc_pollset_destroy(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset) {} grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, @@ -227,6 +229,4 @@ grpc_error *grpc_pollset_kick(grpc_pollset *p, return GRPC_ERROR_NONE; } -void grpc_kick_poller(void) { grpc_iocp_kick(); } - #endif /* GRPC_WINSOCK_SOCKET */ diff --git a/src/core/lib/iomgr/resource_quota.c b/src/core/lib/iomgr/resource_quota.c index c3ee8786517218549abc4a0b907a30a1c8ac6912..6b2b85cce0025cc4a8321fe473d700c31706dcf2 100644 --- a/src/core/lib/iomgr/resource_quota.c +++ b/src/core/lib/iomgr/resource_quota.c @@ -44,7 +44,7 @@ #include "src/core/lib/iomgr/combiner.h" -int grpc_resource_quota_trace = 0; +grpc_tracer_flag grpc_resource_quota_trace = GRPC_TRACER_INITIALIZER(false); #define MEMORY_USAGE_ESTIMATION_MAX 65536 @@ -307,13 +307,14 @@ static bool rq_alloc(grpc_exec_ctx *exec_ctx, resource_user->free_pool = 0; resource_quota->free_pool -= amt; rq_update_estimate(resource_quota); - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "RQ %s %s: grant alloc %" PRId64 " bytes; rq_free_pool -> %" PRId64, resource_quota->name, resource_user->name, amt, resource_quota->free_pool); } - } else if (grpc_resource_quota_trace && resource_user->free_pool >= 0) { + } else if (GRPC_TRACER_ON(grpc_resource_quota_trace) && + resource_user->free_pool >= 0) { gpr_log(GPR_DEBUG, "RQ %s %s: discard already satisfied alloc request", resource_quota->name, resource_user->name); } @@ -342,7 +343,7 @@ static bool rq_reclaim_from_per_user_free_pool( resource_user->free_pool = 0; resource_quota->free_pool += amt; rq_update_estimate(resource_quota); - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "RQ %s %s: reclaim_from_per_user_free_pool %" PRId64 " bytes; rq_free_pool -> %" PRId64, resource_quota->name, resource_user->name, amt, @@ -365,7 +366,7 @@ static bool rq_reclaim(grpc_exec_ctx *exec_ctx, : GRPC_RULIST_RECLAIMER_BENIGN; grpc_resource_user *resource_user = rulist_pop_head(resource_quota, list); if (resource_user == NULL) return false; - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "RQ %s %s: initiate %s reclamation", resource_quota->name, resource_user->name, destructive ? "destructive" : "benign"); @@ -786,7 +787,7 @@ void grpc_resource_user_alloc(grpc_exec_ctx *exec_ctx, gpr_mu_lock(&resource_user->mu); ru_ref_by(resource_user, (gpr_atm)size); resource_user->free_pool -= (int64_t)size; - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64, resource_user->resource_quota->name, resource_user->name, size, resource_user->free_pool); @@ -810,7 +811,7 @@ void grpc_resource_user_free(grpc_exec_ctx *exec_ctx, gpr_mu_lock(&resource_user->mu); bool was_zero_or_negative = resource_user->free_pool <= 0; resource_user->free_pool += (int64_t)size; - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64, resource_user->resource_quota->name, resource_user->name, size, resource_user->free_pool); @@ -839,7 +840,7 @@ void grpc_resource_user_post_reclaimer(grpc_exec_ctx *exec_ctx, void grpc_resource_user_finish_reclamation(grpc_exec_ctx *exec_ctx, grpc_resource_user *resource_user) { - if (grpc_resource_quota_trace) { + if (GRPC_TRACER_ON(grpc_resource_quota_trace)) { gpr_log(GPR_DEBUG, "RQ %s %s: reclamation complete", resource_user->resource_quota->name, resource_user->name); } diff --git a/src/core/lib/iomgr/resource_quota.h b/src/core/lib/iomgr/resource_quota.h index 6f99be0d512e48cdcbdbe5244bba221f79db30cd..51122dad01130f9b1c2d97f566141cfef03ed649 100644 --- a/src/core/lib/iomgr/resource_quota.h +++ b/src/core/lib/iomgr/resource_quota.h @@ -36,6 +36,7 @@ #include <grpc/grpc.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/exec_ctx.h" /** \file Tracks resource usage against a pool. @@ -75,7 +76,7 @@ maintain lists of users (which users arrange to leave before they are destroyed) */ -extern int grpc_resource_quota_trace; +extern grpc_tracer_flag grpc_resource_quota_trace; grpc_resource_quota *grpc_resource_quota_ref_internal( grpc_resource_quota *resource_quota); diff --git a/src/core/lib/iomgr/sys_epoll_wrapper.h b/src/core/lib/iomgr/sys_epoll_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..2f08423193d5814318ea9027aac755e3c436c573 --- /dev/null +++ b/src/core/lib/iomgr/sys_epoll_wrapper.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_SYS_EPOLL_WRAPPER_H +#define GRPC_CORE_LIB_IOMGR_SYS_EPOLL_WRAPPER_H + +#include <sys/epoll.h> + +#ifndef EPOLLEXCLUSIVE +#define EPOLLEXCLUSIVE (1 << 28) +#endif + +#endif /* GRPC_CORE_LIB_IOMGR_SYS_EPOLL_WRAPPER_H */ diff --git a/src/core/lib/iomgr/tcp_client_posix.c b/src/core/lib/iomgr/tcp_client_posix.c index a2692707d9ea5a887244174d4db0fdb4fc971b25..5c7da999e0e6d008bca111c1168382b701079260 100644 --- a/src/core/lib/iomgr/tcp_client_posix.c +++ b/src/core/lib/iomgr/tcp_client_posix.c @@ -58,7 +58,7 @@ #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/support/string.h" -extern int grpc_tcp_trace; +extern grpc_tracer_flag grpc_tcp_trace; typedef struct { gpr_mu mu; @@ -114,7 +114,7 @@ done: static void tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { int done; async_connect *ac = acp; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str, str); @@ -152,7 +152,7 @@ static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { GRPC_ERROR_REF(error); - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s", ac->addr_str, str); @@ -330,9 +330,9 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx, grpc_schedule_on_exec_ctx); ac->channel_args = grpc_channel_args_copy(channel_args); - if (grpc_tcp_trace) { - gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting", - ac->addr_str); + if (GRPC_TRACER_ON(grpc_tcp_trace)) { + gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting fd %p", + ac->addr_str, fdobj); } gpr_mu_lock(&ac->mu); diff --git a/src/core/lib/iomgr/tcp_client_uv.c b/src/core/lib/iomgr/tcp_client_uv.c index 682c24ed56b820b23f47d95aa68af56b4d375d76..f0856a76d4bdcaaa4fb257e128fed8a3ea714bd8 100644 --- a/src/core/lib/iomgr/tcp_client_uv.c +++ b/src/core/lib/iomgr/tcp_client_uv.c @@ -46,7 +46,7 @@ #include "src/core/lib/iomgr/tcp_uv.h" #include "src/core/lib/iomgr/timer.h" -extern int grpc_tcp_trace; +extern grpc_tracer_flag grpc_tcp_trace; typedef struct grpc_uv_tcp_connect { uv_connect_t connect_req; @@ -72,7 +72,7 @@ static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { int done; grpc_uv_tcp_connect *connect = acp; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", connect->addr_name, str); @@ -156,7 +156,7 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx, uv_tcp_init(uv_default_loop(), connect->tcp_handle); connect->connect_req.data = connect; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting", connect->addr_name); } diff --git a/src/core/lib/iomgr/tcp_posix.c b/src/core/lib/iomgr/tcp_posix.c index 5f4b38de2b9c17e0fb02f320dda5a694df75a190..5d360b0b80518eb956a446c37f436cf4e5beea25 100644 --- a/src/core/lib/iomgr/tcp_posix.c +++ b/src/core/lib/iomgr/tcp_posix.c @@ -74,7 +74,7 @@ typedef GRPC_MSG_IOVLEN_TYPE msg_iovlen_type; typedef size_t msg_iovlen_type; #endif -int grpc_tcp_trace = 0; +grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false); typedef struct { grpc_endpoint base; @@ -221,7 +221,7 @@ static void call_read_cb(grpc_exec_ctx *exec_ctx, grpc_tcp *tcp, grpc_error *error) { grpc_closure *cb = tcp->read_cb; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { size_t i; const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "read: error=%s", str); @@ -468,14 +468,14 @@ static void tcp_handle_write(grpc_exec_ctx *exec_ctx, void *arg /* grpc_tcp */, } if (!tcp_flush(tcp, &error)) { - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_log(GPR_DEBUG, "write: delayed"); } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { cb = tcp->write_cb; tcp->write_cb = NULL; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write: %s", str); } @@ -490,7 +490,7 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_tcp *tcp = (grpc_tcp *)ep; grpc_error *error = GRPC_ERROR_NONE; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { size_t i; for (i = 0; i < buf->count; i++) { @@ -521,12 +521,12 @@ static void tcp_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (!tcp_flush(tcp, &error)) { TCP_REF(tcp, "write"); tcp->write_cb = cb; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_log(GPR_DEBUG, "write: delayed"); } grpc_fd_notify_on_write(exec_ctx, tcp->em_fd, &tcp->write_closure); } else { - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write: %s", str); } diff --git a/src/core/lib/iomgr/tcp_posix.h b/src/core/lib/iomgr/tcp_posix.h index 1ad5788331ffd7cc0b525cd90a90ca839fe0b931..4ad60c116eb8e8ea147a82ec2e9461a92cfda58d 100644 --- a/src/core/lib/iomgr/tcp_posix.h +++ b/src/core/lib/iomgr/tcp_posix.h @@ -44,10 +44,11 @@ otherwise specified. */ +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/ev_posix.h" -extern int grpc_tcp_trace; +extern grpc_tracer_flag grpc_tcp_trace; /* Create a tcp endpoint given a file desciptor and a read slice size. Takes ownership of fd. */ diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c index e66ffc9b1c22cf8c56a1910c42d0b9f4b6595f0a..08997b5e2bbc5e06dc204619b590d5307964f71b 100644 --- a/src/core/lib/iomgr/tcp_server_posix.c +++ b/src/core/lib/iomgr/tcp_server_posix.c @@ -257,7 +257,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { addr_str = grpc_sockaddr_to_uri(&addr); gpr_asprintf(&name, "tcp-server-connection:%s", addr_str); - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str); } diff --git a/src/core/lib/iomgr/tcp_uv.c b/src/core/lib/iomgr/tcp_uv.c index 8e8db9f7b45b0de81f7187dd50005805c7ed7072..e7157537f6de289703be0f6b54f6b7f29744e835 100644 --- a/src/core/lib/iomgr/tcp_uv.c +++ b/src/core/lib/iomgr/tcp_uv.c @@ -52,7 +52,7 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/support/string.h" -int grpc_tcp_trace = 0; +grpc_tracer_flag grpc_tcp_trace = GRPC_TRACER_INITIALIZER(false); typedef struct { grpc_endpoint base; @@ -158,7 +158,7 @@ static void read_callback(uv_stream_t *stream, ssize_t nread, sub = grpc_slice_sub_no_ref(tcp->read_slice, 0, (size_t)nread); grpc_slice_buffer_add(tcp->read_slices, sub); error = GRPC_ERROR_NONE; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { size_t i; const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "read: error=%s", str); @@ -199,7 +199,7 @@ static void uv_endpoint_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_from_static_string(uv_strerror(status))); grpc_closure_sched(exec_ctx, cb, error); } - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "Initiating read on %p: error=%s", tcp, str); } @@ -217,7 +217,7 @@ static void write_callback(uv_write_t *req, int status) { } else { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("TCP Write failed"); } - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp, str); } @@ -238,7 +238,7 @@ static void uv_endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice *slice; uv_write_t *write_req; - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { size_t j; for (j = 0; j < write_slices->count; j++) { @@ -346,7 +346,7 @@ grpc_endpoint *grpc_tcp_create(uv_tcp_t *handle, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); - if (grpc_tcp_trace) { + if (GRPC_TRACER_ON(grpc_tcp_trace)) { gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", tcp); } diff --git a/src/core/lib/iomgr/tcp_uv.h b/src/core/lib/iomgr/tcp_uv.h index 970fcafe4a52f7555ea3df4d95b5c69f25f433df..106bec5eca7702a775189e0857190bd498a938fd 100644 --- a/src/core/lib/iomgr/tcp_uv.h +++ b/src/core/lib/iomgr/tcp_uv.h @@ -44,11 +44,12 @@ otherwise specified. */ +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/endpoint.h" #include <uv.h> -extern int grpc_tcp_trace; +extern grpc_tracer_flag grpc_tcp_trace; #define GRPC_TCP_DEFAULT_READ_SLICE_SIZE 8192 diff --git a/src/core/lib/iomgr/timer_generic.c b/src/core/lib/iomgr/timer_generic.c index d8e60684312bda411aed4c2e5fa73336109ab2f8..b28340b71c722801a87e9310dcad29a47e77eec0 100644 --- a/src/core/lib/iomgr/timer_generic.c +++ b/src/core/lib/iomgr/timer_generic.c @@ -56,8 +56,8 @@ #define MIN_QUEUE_WINDOW_DURATION 0.01 #define MAX_QUEUE_WINDOW_DURATION 1 -int grpc_timer_trace = 0; -int grpc_timer_check_trace = 0; +grpc_tracer_flag grpc_timer_trace = GRPC_TRACER_INITIALIZER(false); +grpc_tracer_flag grpc_timer_check_trace = GRPC_TRACER_INITIALIZER(false); typedef struct { gpr_mu mu; @@ -232,14 +232,13 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, GPR_ASSERT(deadline.clock_type == g_clock_type); GPR_ASSERT(now.clock_type == g_clock_type); timer->closure = closure; - timer->deadline = timespec_to_atm_round_up(deadline); + gpr_atm deadline_atm = timer->deadline = timespec_to_atm_round_up(deadline); - if (grpc_timer_trace) { + if (GRPC_TRACER_ON(grpc_timer_trace)) { gpr_log(GPR_DEBUG, "TIMER %p: SET %" PRId64 ".%09d [%" PRIdPTR "] now %" PRId64 ".%09d [%" PRIdPTR "] call %p[%p]", - timer, deadline.tv_sec, deadline.tv_nsec, timer->deadline, - now.tv_sec, now.tv_nsec, timespec_to_atm_round_down(now), closure, - closure->cb); + timer, deadline.tv_sec, deadline.tv_nsec, deadline_atm, now.tv_sec, + now.tv_nsec, timespec_to_atm_round_down(now), closure, closure->cb); } if (!g_shared_mutables.initialized) { @@ -262,13 +261,13 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, grpc_time_averaged_stats_add_sample(&shard->stats, ts_to_dbl(gpr_time_sub(deadline, now))); - if (timer->deadline < shard->queue_deadline_cap) { + if (deadline_atm < shard->queue_deadline_cap) { is_first_timer = grpc_timer_heap_add(&shard->heap, timer); } else { timer->heap_index = INVALID_HEAP_INDEX; list_join(&shard->list, timer); } - if (grpc_timer_trace) { + if (GRPC_TRACER_ON(grpc_timer_trace)) { gpr_log(GPR_DEBUG, " .. add to shard %d with queue_deadline_cap=%" PRIdPTR " => is_first_timer=%s", (int)(shard - g_shards), shard->queue_deadline_cap, @@ -289,16 +288,16 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer, grpc_timer_check. */ if (is_first_timer) { gpr_mu_lock(&g_shared_mutables.mu); - if (grpc_timer_trace) { + if (GRPC_TRACER_ON(grpc_timer_trace)) { gpr_log(GPR_DEBUG, " .. old shard min_deadline=%" PRIdPTR, shard->min_deadline); } - if (timer->deadline < shard->min_deadline) { + if (deadline_atm < shard->min_deadline) { gpr_atm old_min_deadline = g_shard_queue[0]->min_deadline; - shard->min_deadline = timer->deadline; + shard->min_deadline = deadline_atm; note_deadline_change(shard); - if (shard->shard_queue_index == 0 && timer->deadline < old_min_deadline) { - gpr_atm_no_barrier_store(&g_shared_mutables.min_timer, timer->deadline); + if (shard->shard_queue_index == 0 && deadline_atm < old_min_deadline) { + gpr_atm_no_barrier_store(&g_shared_mutables.min_timer, deadline_atm); grpc_kick_poller(); } } @@ -319,7 +318,7 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) { shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)]; gpr_mu_lock(&shard->mu); - if (grpc_timer_trace) { + if (GRPC_TRACER_ON(grpc_timer_trace)) { gpr_log(GPR_DEBUG, "TIMER %p: CANCEL pending=%s", timer, timer->pending ? "true" : "false"); } @@ -355,7 +354,7 @@ static int refill_queue(shard_type *shard, gpr_atm now) { saturating_add(GPR_MAX(now, shard->queue_deadline_cap), (gpr_atm)(deadline_delta * 1000.0)); - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, " .. shard[%d]->queue_deadline_cap --> %" PRIdPTR, (int)(shard - g_shards), shard->queue_deadline_cap); } @@ -363,7 +362,7 @@ static int refill_queue(shard_type *shard, gpr_atm now) { next = timer->next; if (timer->deadline < shard->queue_deadline_cap) { - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, " .. add timer with deadline %" PRIdPTR " to heap", timer->deadline); } @@ -380,7 +379,7 @@ static int refill_queue(shard_type *shard, gpr_atm now) { static grpc_timer *pop_one(shard_type *shard, gpr_atm now) { grpc_timer *timer; for (;;) { - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, " .. shard[%d]: heap_empty=%s", (int)(shard - g_shards), grpc_timer_heap_is_empty(&shard->heap) ? "true" : "false"); @@ -390,13 +389,13 @@ static grpc_timer *pop_one(shard_type *shard, gpr_atm now) { if (!refill_queue(shard, now)) return NULL; } timer = grpc_timer_heap_top(&shard->heap); - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, " .. check top timer deadline=%" PRIdPTR " now=%" PRIdPTR, timer->deadline, now); } if (timer->deadline > now) return NULL; - if (grpc_timer_trace) { + if (GRPC_TRACER_ON(grpc_timer_trace)) { gpr_log(GPR_DEBUG, "TIMER %p: FIRE %" PRIdPTR "ms late", timer, now - timer->deadline); } @@ -436,7 +435,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_atm now, if (gpr_spinlock_trylock(&g_shared_mutables.checker_mu)) { gpr_mu_lock(&g_shared_mutables.mu); - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, " .. shard[%d]->min_deadline = %" PRIdPTR, (int)(g_shard_queue[0] - g_shards), g_shard_queue[0]->min_deadline); @@ -452,7 +451,7 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_atm now, n += pop_timers(exec_ctx, g_shard_queue[0], now, &new_min_deadline, error); - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, " .. popped --> %" PRIdPTR ", shard[%d]->min_deadline %" PRIdPTR " --> %" PRIdPTR ", now=%" PRIdPTR, @@ -509,7 +508,7 @@ bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, *next = atm_to_timespec(GPR_MIN(timespec_to_atm_round_up(*next), min_timer)); } - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { gpr_log(GPR_DEBUG, "TIMER CHECK SKIP: now_atm=%" PRIdPTR " min_timer=%" PRIdPTR, now_atm, min_timer); @@ -523,7 +522,7 @@ bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, : GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutting down timer system"); // tracing - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { char *next_str; if (next == NULL) { next_str = gpr_strdup("NULL"); @@ -549,7 +548,7 @@ bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, *next = atm_to_timespec(next_atm); } // tracing - if (grpc_timer_check_trace) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { char *next_str; if (next == NULL) { next_str = gpr_strdup("NULL"); diff --git a/src/core/lib/iomgr/timer_manager.c b/src/core/lib/iomgr/timer_manager.c new file mode 100644 index 0000000000000000000000000000000000000000..24085093e70ddfe59753fe07e79244a53f5c9789 --- /dev/null +++ b/src/core/lib/iomgr/timer_manager.c @@ -0,0 +1,276 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/timer_manager.h" + +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/thd.h> + +#include "src/core/lib/debug/trace.h" +#include "src/core/lib/iomgr/timer.h" + +typedef struct completed_thread { + gpr_thd_id t; + struct completed_thread *next; +} completed_thread; + +extern grpc_tracer_flag grpc_timer_check_trace; + +// global mutex +static gpr_mu g_mu; +// are we multi-threaded +static bool g_threaded; +// cv to wait until a thread is needed +static gpr_cv g_cv_wait; +// cv for notification when threading ends +static gpr_cv g_cv_shutdown; +// number of threads in the system +static int g_thread_count; +// number of threads sitting around waiting +static int g_waiter_count; +// linked list of threads that have completed (and need joining) +static completed_thread *g_completed_threads; +// was the manager kicked by the timer system +static bool g_kicked; +// is there a thread waiting until the next timer should fire? +static bool g_has_timed_waiter; +// generation counter to track which thread is waiting for the next timer +static uint64_t g_timed_waiter_generation; + +static void timer_thread(void *unused); + +static void gc_completed_threads(void) { + if (g_completed_threads != NULL) { + completed_thread *to_gc = g_completed_threads; + g_completed_threads = NULL; + gpr_mu_unlock(&g_mu); + while (to_gc != NULL) { + gpr_thd_join(to_gc->t); + completed_thread *next = to_gc->next; + gpr_free(to_gc); + to_gc = next; + } + gpr_mu_lock(&g_mu); + } +} + +static void start_timer_thread_and_unlock(void) { + GPR_ASSERT(g_threaded); + ++g_waiter_count; + ++g_thread_count; + gpr_mu_unlock(&g_mu); + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "Spawn timer thread"); + } + gpr_thd_id thd; + gpr_thd_options opt = gpr_thd_options_default(); + gpr_thd_options_set_joinable(&opt); + gpr_thd_new(&thd, timer_thread, NULL, &opt); +} + +void grpc_timer_manager_tick() { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + gpr_timespec next = gpr_inf_future(GPR_CLOCK_MONOTONIC); + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + grpc_timer_check(&exec_ctx, now, &next); + grpc_exec_ctx_finish(&exec_ctx); +} + +static void timer_thread(void *unused) { + // this threads exec_ctx: we try to run things through to completion here + // since it's easy to spin up new threads + grpc_exec_ctx exec_ctx = + GRPC_EXEC_CTX_INITIALIZER(0, grpc_never_ready_to_finish, NULL); + const gpr_timespec inf_future = gpr_inf_future(GPR_CLOCK_MONOTONIC); + for (;;) { + gpr_timespec next = inf_future; + gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + // check timer state, updates next to the next time to run a check + if (grpc_timer_check(&exec_ctx, now, &next)) { + // if there's something to execute... + gpr_mu_lock(&g_mu); + // remove a waiter from the pool, and start another thread if necessary + --g_waiter_count; + if (g_waiter_count == 0 && g_threaded) { + start_timer_thread_and_unlock(); + } else { + // if there's no thread waiting with a timeout, kick an existing waiter + // so that the next deadline is not missed + if (!g_has_timed_waiter) { + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "kick untimed waiter"); + } + gpr_cv_signal(&g_cv_wait); + } + gpr_mu_unlock(&g_mu); + } + // without our lock, flush the exec_ctx + grpc_exec_ctx_flush(&exec_ctx); + gpr_mu_lock(&g_mu); + // garbage collect any threads hanging out that are dead + gc_completed_threads(); + // get ready to wait again + ++g_waiter_count; + gpr_mu_unlock(&g_mu); + } else { + gpr_mu_lock(&g_mu); + // if we're not threaded anymore, leave + if (!g_threaded) break; + // if there's no timed waiter, we should become one: that waiter waits + // only until the next timer should expire + // all other timers wait forever + uint64_t my_timed_waiter_generation = g_timed_waiter_generation - 1; + if (!g_has_timed_waiter) { + g_has_timed_waiter = true; + // we use a generation counter to track the timed waiter so we can + // cancel an existing one quickly (and when it actually times out it'll + // figure stuff out instead of incurring a wakeup) + my_timed_waiter_generation = ++g_timed_waiter_generation; + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "sleep for a while"); + } + } else { + next = inf_future; + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "sleep until kicked"); + } + } + gpr_cv_wait(&g_cv_wait, &g_mu, next); + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "wait ended: was_timed:%d kicked:%d", + my_timed_waiter_generation == g_timed_waiter_generation, + g_kicked); + } + // if this was the timed waiter, then we need to check timers, and flag + // that there's now no timed waiter... we'll look for a replacement if + // there's work to do after checking timers (code above) + if (my_timed_waiter_generation == g_timed_waiter_generation) { + g_has_timed_waiter = false; + } + // if this was a kick from the timer system, consume it (and don't stop + // this thread yet) + if (g_kicked) { + grpc_timer_consume_kick(); + g_kicked = false; + } + gpr_mu_unlock(&g_mu); + } + } + // terminate the thread: drop the waiter count, thread count, and let whomever + // stopped the threading stuff know that we're done + --g_waiter_count; + --g_thread_count; + if (0 == g_thread_count) { + gpr_cv_signal(&g_cv_shutdown); + } + completed_thread *ct = gpr_malloc(sizeof(*ct)); + ct->t = gpr_thd_currentid(); + ct->next = g_completed_threads; + g_completed_threads = ct; + gpr_mu_unlock(&g_mu); + grpc_exec_ctx_finish(&exec_ctx); + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "End timer thread"); + } +} + +static void start_threads(void) { + gpr_mu_lock(&g_mu); + if (!g_threaded) { + g_threaded = true; + start_timer_thread_and_unlock(); + } else { + g_threaded = false; + gpr_mu_unlock(&g_mu); + } +} + +void grpc_timer_manager_init(void) { + gpr_mu_init(&g_mu); + gpr_cv_init(&g_cv_wait); + gpr_cv_init(&g_cv_shutdown); + g_threaded = false; + g_thread_count = 0; + g_waiter_count = 0; + g_completed_threads = NULL; + + start_threads(); +} + +static void stop_threads(void) { + gpr_mu_lock(&g_mu); + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "stop timer threads: threaded=%d", g_threaded); + } + if (g_threaded) { + g_threaded = false; + gpr_cv_broadcast(&g_cv_wait); + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count); + } + while (g_thread_count > 0) { + gpr_cv_wait(&g_cv_shutdown, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + if (GRPC_TRACER_ON(grpc_timer_check_trace)) { + gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count); + } + gc_completed_threads(); + } + } + gpr_mu_unlock(&g_mu); +} + +void grpc_timer_manager_shutdown(void) { + stop_threads(); + + gpr_mu_destroy(&g_mu); + gpr_cv_destroy(&g_cv_wait); + gpr_cv_destroy(&g_cv_shutdown); +} + +void grpc_timer_manager_set_threading(bool threaded) { + if (threaded) { + start_threads(); + } else { + stop_threads(); + } +} + +void grpc_kick_poller(void) { + gpr_mu_lock(&g_mu); + g_kicked = true; + g_has_timed_waiter = false; + ++g_timed_waiter_generation; + gpr_cv_signal(&g_cv_wait); + gpr_mu_unlock(&g_mu); +} diff --git a/src/core/lib/iomgr/timer_manager.h b/src/core/lib/iomgr/timer_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..46729ccea629416e68d1e1c43e701f6d513c254f --- /dev/null +++ b/src/core/lib/iomgr/timer_manager.h @@ -0,0 +1,52 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_LIB_IOMGR_TIMER_MANAGER_H +#define GRPC_CORE_LIB_IOMGR_TIMER_MANAGER_H + +#include <stdbool.h> + +/* Timer Manager tries to keep one thread waiting for the next timeout at all + times */ + +void grpc_timer_manager_init(void); +void grpc_timer_manager_shutdown(void); + +/* enable/disable threading - must be called after grpc_timer_manager_init and + * before grpc_timer_manager_shutdown */ +void grpc_timer_manager_set_threading(bool enabled); +/* explicitly perform one tick of the timer system - for when threading is + * disabled */ +void grpc_timer_manager_tick(void); + +#endif /* GRPC_CORE_LIB_IOMGR_TIMER_MANAGER_H */ diff --git a/src/core/lib/iomgr/timer_uv.c b/src/core/lib/iomgr/timer_uv.c index 8e8a07578c6a6d693e10e48816d8401e3776174f..2952e44b5832cec0b13ded78beb475da17eef73d 100644 --- a/src/core/lib/iomgr/timer_uv.c +++ b/src/core/lib/iomgr/timer_uv.c @@ -38,10 +38,14 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/timer.h" #include <uv.h> +grpc_tracer_flag grpc_timer_trace = GRPC_TRACER_INITIALIZER(false); +grpc_tracer_flag grpc_timer_check_trace = GRPC_TRACER_INITIALIZER(false); + static void timer_close_callback(uv_handle_t *handle) { gpr_free(handle); } static void stop_uv_timer(uv_timer_t *handle) { @@ -100,4 +104,6 @@ bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now, void grpc_timer_list_init(gpr_timespec now) {} void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {} +void grpc_timer_consume_kick(void) {} + #endif /* GRPC_UV */ diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.c b/src/core/lib/security/credentials/google_default/google_default_credentials.c index 97501e6788ca05513e83967191bd17793549ac3a..4d8c451ea806db13abd79929ac4b0ac66261ac42 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.c +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.c @@ -99,7 +99,7 @@ static void on_compute_engine_detection_http_response(grpc_exec_ctx *exec_ctx, } static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *e) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } static int is_stack_running_on_compute_engine(grpc_exec_ctx *exec_ctx) { diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.c b/src/core/lib/security/credentials/jwt/jwt_credentials.c index 178ce89aa6942b588d04fb17f806215055966272..0e7c1afb024d4aee9c2b66ef5f37dedf1016713d 100644 --- a/src/core/lib/security/credentials/jwt/jwt_credentials.c +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.c @@ -171,7 +171,7 @@ static char *redact_private_key(const char *json_key) { grpc_call_credentials *grpc_service_account_jwt_access_credentials_create( const char *json_key, gpr_timespec token_lifetime, void *reserved) { - if (grpc_api_trace) { + if (GRPC_TRACER_ON(grpc_api_trace)) { char *clean_json = redact_private_key(json_key); gpr_log(GPR_INFO, "grpc_service_account_jwt_access_credentials_create(" diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c index ccfb3566c1127bd319f39c0f737d1ebe72d67c1f..29235b6eb30964ab38c3f1de07c5cca8648d9ff3 100644 --- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.c @@ -412,7 +412,7 @@ grpc_call_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved) { grpc_auth_refresh_token token = grpc_auth_refresh_token_create_from_string(json_refresh_token); - if (grpc_api_trace) { + if (GRPC_TRACER_ON(grpc_api_trace)) { char *loggable_token = create_loggable_refresh_token(&token); gpr_log(GPR_INFO, "grpc_refresh_token_credentials_create(json_refresh_token=%s, " diff --git a/src/core/lib/security/transport/client_auth_filter.c b/src/core/lib/security/transport/client_auth_filter.c index 1f0daf73253e6ae7ebbaa02cd1083ce801534121..dff05633ecb97341bbd6025a62a0bac68bf9ec9b 100644 --- a/src/core/lib/security/transport/client_auth_filter.c +++ b/src/core/lib/security/transport/client_auth_filter.c @@ -253,7 +253,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx, grpc_linked_mdelem *l; grpc_client_security_context *sec_ctx = NULL; - if (calld->security_context_set == 0 && !op->cancel_stream) { + if (!op->cancel_stream && calld->security_context_set == 0) { calld->security_context_set = 1; GPR_ASSERT(op->payload->context != NULL); if (op->payload->context[GRPC_CONTEXT_SECURITY].value == NULL) { diff --git a/src/core/lib/security/transport/secure_endpoint.c b/src/core/lib/security/transport/secure_endpoint.c index 0d5c7432c645d299a050fa76d61fa3e6b2bdeea9..48d368a2a70bc405ccaab5d97c288e2aaaa8c43e 100644 --- a/src/core/lib/security/transport/secure_endpoint.c +++ b/src/core/lib/security/transport/secure_endpoint.c @@ -75,7 +75,7 @@ typedef struct { gpr_refcount ref; } secure_endpoint; -int grpc_trace_secure_endpoint = 0; +grpc_tracer_flag grpc_trace_secure_endpoint = GRPC_TRACER_INITIALIZER(false); static void destroy(grpc_exec_ctx *exec_ctx, secure_endpoint *secure_ep) { secure_endpoint *ep = secure_ep; @@ -137,7 +137,7 @@ static void flush_read_staging_buffer(secure_endpoint *ep, uint8_t **cur, static void call_read_cb(grpc_exec_ctx *exec_ctx, secure_endpoint *ep, grpc_error *error) { - if (grpc_trace_secure_endpoint) { + if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) { size_t i; for (i = 0; i < ep->read_buffer->count; i++) { char *data = grpc_dump_slice(ep->read_buffer->slices[i], @@ -269,7 +269,7 @@ static void endpoint_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *secure_ep, grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &ep->output_buffer); - if (grpc_trace_secure_endpoint) { + if (GRPC_TRACER_ON(grpc_trace_secure_endpoint)) { for (i = 0; i < slices->count; i++) { char *data = grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); diff --git a/src/core/lib/security/transport/secure_endpoint.h b/src/core/lib/security/transport/secure_endpoint.h index a61f40a4fa3fc99d15591e0975a2a64645606dbc..f1a5c8cb6de417b819f3e227828b8972259f5d76 100644 --- a/src/core/lib/security/transport/secure_endpoint.h +++ b/src/core/lib/security/transport/secure_endpoint.h @@ -39,7 +39,7 @@ struct tsi_frame_protector; -extern int grpc_trace_secure_endpoint; +extern grpc_tracer_flag grpc_trace_secure_endpoint; /* Takes ownership of protector and to_wrap, and refs leftover_slices. */ grpc_endpoint *grpc_secure_endpoint_create( diff --git a/src/core/lib/support/mpscq.c b/src/core/lib/support/mpscq.c index 5b9323275aa49825b7858e78167ab0180b89f512..1015cc67765d6dab4abbe26f8ee344fc325be901 100644 --- a/src/core/lib/support/mpscq.c +++ b/src/core/lib/support/mpscq.c @@ -54,21 +54,31 @@ void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { } gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { + bool empty; + return gpr_mpscq_pop_and_check_end(q, &empty); +} + +gpr_mpscq_node *gpr_mpscq_pop_and_check_end(gpr_mpscq *q, bool *empty) { gpr_mpscq_node *tail = q->tail; gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); if (tail == &q->stub) { // indicates the list is actually (ephemerally) empty - if (next == NULL) return NULL; + if (next == NULL) { + *empty = true; + return NULL; + } q->tail = next; tail = next; next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); } if (next != NULL) { + *empty = false; q->tail = next; return tail; } gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); if (tail != head) { + *empty = false; // indicates a retry is in order: we're still adding return NULL; } @@ -79,5 +89,6 @@ gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { return tail; } // indicates a retry is in order: we're still adding + *empty = false; return NULL; } diff --git a/src/core/lib/support/mpscq.h b/src/core/lib/support/mpscq.h index 977a117952979604a3ffaf8d7e25103b5b2b562e..24c89f90c9d214d0de38897a0a3e4cd08d37064d 100644 --- a/src/core/lib/support/mpscq.h +++ b/src/core/lib/support/mpscq.h @@ -35,6 +35,7 @@ #define GRPC_CORE_LIB_SUPPORT_MPSCQ_H #include <grpc/support/atm.h> +#include <stdbool.h> #include <stddef.h> // Multiple-producer single-consumer lock free queue, based upon the @@ -62,4 +63,7 @@ void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n); // the queue is empty!!) gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q); +// Pop a node; sets *empty to true if the queue is empty, or false if it is not +gpr_mpscq_node *gpr_mpscq_pop_and_check_end(gpr_mpscq *q, bool *empty); + #endif /* GRPC_CORE_LIB_SUPPORT_MPSCQ_H */ diff --git a/src/core/lib/surface/alarm.c b/src/core/lib/surface/alarm.c index e71c0ebfc57c557854098774251af31560c925c2..b72d534b7efa75f79a8666186c5f9d4e4ab7a3bd 100644 --- a/src/core/lib/surface/alarm.c +++ b/src/core/lib/surface/alarm.c @@ -81,7 +81,9 @@ void grpc_alarm_cancel(grpc_alarm *alarm) { } void grpc_alarm_destroy(grpc_alarm *alarm) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_alarm_cancel(alarm); - GRPC_CQ_INTERNAL_UNREF(alarm->cq, "alarm"); + GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm"); gpr_free(alarm); + grpc_exec_ctx_finish(&exec_ctx); } diff --git a/src/core/lib/surface/api_trace.c b/src/core/lib/surface/api_trace.c index 79e3e5ca9b8b746dd9ad3977994fc7751640bcff..d8941cdf426e2b644586ca5fa230506115859732 100644 --- a/src/core/lib/surface/api_trace.c +++ b/src/core/lib/surface/api_trace.c @@ -32,5 +32,6 @@ */ #include "src/core/lib/surface/api_trace.h" +#include "src/core/lib/debug/trace.h" -int grpc_api_trace = 0; +grpc_tracer_flag grpc_api_trace = GRPC_TRACER_INITIALIZER(false); diff --git a/src/core/lib/surface/api_trace.h b/src/core/lib/surface/api_trace.h index c60aaba5e97e90030a97b49c8ecaadba524b19b6..d4fbc8d90d377832095f0af412bd1481bc5bc3db 100644 --- a/src/core/lib/surface/api_trace.h +++ b/src/core/lib/surface/api_trace.h @@ -37,7 +37,7 @@ #include <grpc/support/log.h> #include "src/core/lib/debug/trace.h" -extern int grpc_api_trace; +extern grpc_tracer_flag grpc_api_trace; /* Provide unwrapping macros because we're in C89 and variadic macros weren't introduced until C99... */ @@ -58,7 +58,7 @@ extern int grpc_api_trace; /* Due to the limitations of C89's preprocessor, the arity of the var-arg list 'nargs' must be specified. */ #define GRPC_API_TRACE(fmt, nargs, args) \ - if (grpc_api_trace) { \ + if (GRPC_TRACER_ON(grpc_api_trace)) { \ gpr_log(GPR_INFO, fmt GRPC_API_TRACE_UNWRAP##nargs args); \ } diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c index 752580658305e180642a5cdffdc363edf5b9f5de..201969cd456848b83151ad922ab15d4270182f30 100644 --- a/src/core/lib/surface/call.c +++ b/src/core/lib/surface/call.c @@ -244,8 +244,8 @@ struct grpc_call { void *saved_receiving_stream_ready_bctlp; }; -int grpc_call_error_trace = 0; -int grpc_compression_trace = 0; +grpc_tracer_flag grpc_call_error_trace = GRPC_TRACER_INITIALIZER(false); +grpc_tracer_flag grpc_compression_trace = GRPC_TRACER_INITIALIZER(false); #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) @@ -521,7 +521,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, } } if (c->cq) { - GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); + GRPC_CQ_INTERNAL_UNREF(exec_ctx, c->cq, "bind"); } get_final_status(call, set_status_value_directly, &c->final_info.final_status, @@ -702,7 +702,7 @@ static void get_final_status(grpc_call *call, for (i = 0; i < STATUS_SOURCE_COUNT; i++) { status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i])); } - if (grpc_call_error_trace) { + if (GRPC_TRACER_ON(grpc_call_error_trace)) { gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR"); for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (status[i].is_set) { @@ -1259,7 +1259,7 @@ static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp, } if (error != GRPC_ERROR_NONE) { - if (grpc_trace_operation_failures) { + if (GRPC_TRACER_ON(grpc_trace_operation_failures)) { GRPC_LOG_IF_ERROR("receiving_slice_ready", GRPC_ERROR_REF(error)); } grpc_byte_stream_destroy(exec_ctx, call->receiving_stream); @@ -1355,8 +1355,7 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx, GPR_ASSERT(call->encodings_accepted_by_peer != 0); if (!GPR_BITGET(call->encodings_accepted_by_peer, call->incoming_compression_algorithm)) { - extern int grpc_compression_trace; - if (grpc_compression_trace) { + if (GRPC_TRACER_ON(grpc_compression_trace)) { char *algo_name = NULL; grpc_compression_algorithm_name(call->incoming_compression_algorithm, &algo_name); diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index 7d4d0db28d999282940d236e87703e95cdbf8211..256a5fa2feb63ff302475875caed2ca7f73f671f 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -117,7 +117,8 @@ void grpc_call_context_set(grpc_call *call, grpc_context_index elem, void *grpc_call_context_get(grpc_call *call, grpc_context_index elem); #define GRPC_CALL_LOG_BATCH(sev, call, ops, nops, tag) \ - if (grpc_api_trace) grpc_call_log_batch(sev, call, ops, nops, tag) + if (GRPC_TRACER_ON(grpc_api_trace)) \ + grpc_call_log_batch(sev, call, ops, nops, tag) uint8_t grpc_call_is_client(grpc_call *call); @@ -126,7 +127,8 @@ uint8_t grpc_call_is_client(grpc_call *call); grpc_compression_algorithm grpc_call_compression_for_level( grpc_call *call, grpc_compression_level level); -extern int grpc_call_error_trace; +extern grpc_tracer_flag grpc_call_error_trace; +extern grpc_tracer_flag grpc_compression_trace; #ifdef __cplusplus } diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c index eae3f103b1200263183f3bb99266787e1eb8d352..df5b70205cbf71c5d7836fea22953252ad13aa7b 100644 --- a/src/core/lib/surface/completion_queue.c +++ b/src/core/lib/surface/completion_queue.c @@ -50,9 +50,9 @@ #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/event_string.h" -int grpc_trace_operation_failures; +grpc_tracer_flag grpc_trace_operation_failures = GRPC_TRACER_INITIALIZER(false); #ifndef NDEBUG -int grpc_trace_pending_tags; +grpc_tracer_flag grpc_trace_pending_tags = GRPC_TRACER_INITIALIZER(false); #endif typedef struct { @@ -72,7 +72,7 @@ typedef struct { gpr_timespec deadline); void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); - void (*destroy)(grpc_pollset *pollset); + void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset); } cq_poller_vtable; typedef struct non_polling_worker { @@ -98,7 +98,8 @@ static void non_polling_poller_init(grpc_pollset *pollset, gpr_mu **mu) { *mu = &npp->mu; } -static void non_polling_poller_destroy(grpc_pollset *pollset) { +static void non_polling_poller_destroy(grpc_exec_ctx *exec_ctx, + grpc_pollset *pollset) { non_polling_poller *npp = (non_polling_poller *)pollset; gpr_mu_destroy(&npp->mu); } @@ -242,15 +243,16 @@ struct grpc_completion_queue { #define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1)) #define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1) -int grpc_cq_pluck_trace; -int grpc_cq_event_timeout_trace; +grpc_tracer_flag grpc_cq_pluck_trace = GRPC_TRACER_INITIALIZER(true); +grpc_tracer_flag grpc_cq_event_timeout_trace = GRPC_TRACER_INITIALIZER(true); -#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \ - if (grpc_api_trace && \ - (grpc_cq_pluck_trace || (event)->type != GRPC_QUEUE_TIMEOUT)) { \ - char *_ev = grpc_event_string(event); \ - gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \ - gpr_free(_ev); \ +#define GRPC_SURFACE_TRACE_RETURNED_EVENT(cq, event) \ + if (GRPC_TRACER_ON(grpc_api_trace) && \ + (GRPC_TRACER_ON(grpc_cq_pluck_trace) || \ + (event)->type != GRPC_QUEUE_TIMEOUT)) { \ + char *_ev = grpc_event_string(event); \ + gpr_log(GPR_INFO, "RETURN_EVENT[%p]: %s", cq, _ev); \ + gpr_free(_ev); \ } static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc, @@ -322,20 +324,21 @@ void grpc_cq_internal_ref(grpc_completion_queue *cc) { static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { grpc_completion_queue *cc = arg; - GRPC_CQ_INTERNAL_UNREF(cc, "pollset_destroy"); + GRPC_CQ_INTERNAL_UNREF(exec_ctx, cc, "pollset_destroy"); } #ifdef GRPC_CQ_REF_COUNT_DEBUG -void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason, - const char *file, int line) { +void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, + const char *reason, const char *file, int line) { gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "CQ:%p unref %d -> %d %s", cc, (int)cc->owning_refs.count, (int)cc->owning_refs.count - 1, reason); #else -void grpc_cq_internal_unref(grpc_completion_queue *cc) { +void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, + grpc_completion_queue *cc) { #endif if (gpr_unref(&cc->owning_refs)) { GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head); - cc->poller_vtable->destroy(POLLSET_FROM_CQ(cc)); + cc->poller_vtable->destroy(exec_ctx, POLLSET_FROM_CQ(cc)); #ifndef NDEBUG gpr_free(cc->outstanding_tags); #endif @@ -375,14 +378,16 @@ void grpc_cq_end_op(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, #endif GPR_TIMER_BEGIN("grpc_cq_end_op", 0); - if (grpc_api_trace || - (grpc_trace_operation_failures && error != GRPC_ERROR_NONE)) { + if (GRPC_TRACER_ON(grpc_api_trace) || + (GRPC_TRACER_ON(grpc_trace_operation_failures) && + error != GRPC_ERROR_NONE)) { const char *errmsg = grpc_error_string(error); GRPC_API_TRACE( "grpc_cq_end_op(exec_ctx=%p, cc=%p, tag=%p, error=%s, done=%p, " "done_arg=%p, storage=%p)", 7, (exec_ctx, cc, tag, errmsg, done, done_arg, storage)); - if (grpc_trace_operation_failures && error != GRPC_ERROR_NONE) { + if (GRPC_TRACER_ON(grpc_trace_operation_failures) && + error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg); } } @@ -481,7 +486,7 @@ static bool cq_is_next_finished(grpc_exec_ctx *exec_ctx, void *arg) { #ifndef NDEBUG static void dump_pending_tags(grpc_completion_queue *cc) { - if (!grpc_trace_pending_tags) return; + if (!GRPC_TRACER_ON(grpc_trace_pending_tags)) return; gpr_strvec v; gpr_strvec_init(&v); @@ -580,36 +585,23 @@ grpc_event grpc_completion_queue_next(grpc_completion_queue *cc, dump_pending_tags(cc); break; } - /* Check alarms - these are a global resource so we just ping - each time through on every pollset. - May update deadline to ensure timely wakeups. - TODO(ctiller): can this work be localized? */ - gpr_timespec iteration_deadline = deadline; - if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) { - GPR_TIMER_MARK("alarm_triggered", 0); + grpc_error *err = cc->poller_vtable->work(&exec_ctx, POLLSET_FROM_CQ(cc), + NULL, now, deadline); + if (err != GRPC_ERROR_NONE) { gpr_mu_unlock(cc->mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(cc->mu); - continue; - } else { - grpc_error *err = cc->poller_vtable->work(&exec_ctx, POLLSET_FROM_CQ(cc), - NULL, now, iteration_deadline); - if (err != GRPC_ERROR_NONE) { - gpr_mu_unlock(cc->mu); - const char *msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); + const char *msg = grpc_error_string(err); + gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); - GRPC_ERROR_UNREF(err); - memset(&ret, 0, sizeof(ret)); - ret.type = GRPC_QUEUE_TIMEOUT; - dump_pending_tags(cc); - break; - } + GRPC_ERROR_UNREF(err); + memset(&ret, 0, sizeof(ret)); + ret.type = GRPC_QUEUE_TIMEOUT; + dump_pending_tags(cc); + break; } is_finished_arg.first_loop = false; } GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); - GRPC_CQ_INTERNAL_UNREF(cc, "next"); + GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cc, "next"); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(is_finished_arg.stolen_completion == NULL); @@ -690,7 +682,7 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, abort(); } - if (grpc_cq_pluck_trace) { + if (GRPC_TRACER_ON(grpc_cq_pluck_trace)) { GRPC_API_TRACE( "grpc_completion_queue_pluck(" "cc=%p, tag=%p, " @@ -773,38 +765,26 @@ grpc_event grpc_completion_queue_pluck(grpc_completion_queue *cc, void *tag, dump_pending_tags(cc); break; } - /* Check alarms - these are a global resource so we just ping - each time through on every pollset. - May update deadline to ensure timely wakeups. - TODO(ctiller): can this work be localized? */ - gpr_timespec iteration_deadline = deadline; - if (grpc_timer_check(&exec_ctx, now, &iteration_deadline)) { - GPR_TIMER_MARK("alarm_triggered", 0); + grpc_error *err = cc->poller_vtable->work(&exec_ctx, POLLSET_FROM_CQ(cc), + &worker, now, deadline); + if (err != GRPC_ERROR_NONE) { + del_plucker(cc, tag, &worker); gpr_mu_unlock(cc->mu); - grpc_exec_ctx_flush(&exec_ctx); - gpr_mu_lock(cc->mu); - } else { - grpc_error *err = cc->poller_vtable->work( - &exec_ctx, POLLSET_FROM_CQ(cc), &worker, now, iteration_deadline); - if (err != GRPC_ERROR_NONE) { - del_plucker(cc, tag, &worker); - gpr_mu_unlock(cc->mu); - const char *msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); + const char *msg = grpc_error_string(err); + gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); - GRPC_ERROR_UNREF(err); - memset(&ret, 0, sizeof(ret)); - ret.type = GRPC_QUEUE_TIMEOUT; - dump_pending_tags(cc); - break; - } + GRPC_ERROR_UNREF(err); + memset(&ret, 0, sizeof(ret)); + ret.type = GRPC_QUEUE_TIMEOUT; + dump_pending_tags(cc); + break; } is_finished_arg.first_loop = false; del_plucker(cc, tag, &worker); } done: GRPC_SURFACE_TRACE_RETURNED_EVENT(cc, &ret); - GRPC_CQ_INTERNAL_UNREF(cc, "pluck"); + GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cc, "pluck"); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(is_finished_arg.stolen_completion == NULL); @@ -841,7 +821,9 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cc) { GRPC_API_TRACE("grpc_completion_queue_destroy(cc=%p)", 1, (cc)); GPR_TIMER_BEGIN("grpc_completion_queue_destroy", 0); grpc_completion_queue_shutdown(cc); - GRPC_CQ_INTERNAL_UNREF(cc, "destroy"); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + GRPC_CQ_INTERNAL_UNREF(&exec_ctx, cc, "destroy"); + grpc_exec_ctx_finish(&exec_ctx); GPR_TIMER_END("grpc_completion_queue_destroy", 0); } diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h index a932087939d028f19f62685bfa81ed544693c12f..8d9ce2ec02f74dcf15e8a52c20083fddfe71a807 100644 --- a/src/core/lib/surface/completion_queue.h +++ b/src/core/lib/surface/completion_queue.h @@ -37,15 +37,16 @@ /* Internal API for completion queues */ #include <grpc/grpc.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/pollset.h" /* These trace flags default to 1. The corresponding lines are only traced if grpc_api_trace is also truthy */ -extern int grpc_cq_pluck_trace; -extern int grpc_cq_event_timeout_trace; -extern int grpc_trace_operation_failures; +extern grpc_tracer_flag grpc_cq_pluck_trace; +extern grpc_tracer_flag grpc_cq_event_timeout_trace; +extern grpc_tracer_flag grpc_trace_operation_failures; #ifndef NDEBUG -extern int grpc_trace_pending_tags; +extern grpc_tracer_flag grpc_trace_pending_tags; #endif typedef struct grpc_cq_completion { @@ -65,17 +66,17 @@ typedef struct grpc_cq_completion { #ifdef GRPC_CQ_REF_COUNT_DEBUG void grpc_cq_internal_ref(grpc_completion_queue *cc, const char *reason, const char *file, int line); -void grpc_cq_internal_unref(grpc_completion_queue *cc, const char *reason, - const char *file, int line); +void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc, + const char *reason, const char *file, int line); #define GRPC_CQ_INTERNAL_REF(cc, reason) \ grpc_cq_internal_ref(cc, reason, __FILE__, __LINE__) -#define GRPC_CQ_INTERNAL_UNREF(cc, reason) \ - grpc_cq_internal_unref(cc, reason, __FILE__, __LINE__) +#define GRPC_CQ_INTERNAL_UNREF(ec, cc, reason) \ + grpc_cq_internal_unref(ec, cc, reason, __FILE__, __LINE__) #else void grpc_cq_internal_ref(grpc_completion_queue *cc); -void grpc_cq_internal_unref(grpc_completion_queue *cc); +void grpc_cq_internal_unref(grpc_exec_ctx *exec_ctx, grpc_completion_queue *cc); #define GRPC_CQ_INTERNAL_REF(cc, reason) grpc_cq_internal_ref(cc) -#define GRPC_CQ_INTERNAL_UNREF(cc, reason) grpc_cq_internal_unref(cc) +#define GRPC_CQ_INTERNAL_UNREF(ec, cc, reason) grpc_cq_internal_unref(ec, cc) #endif /* Flag that an operation is beginning: the completion channel will not finish diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index 4b381b19546d32eed9a0ad0eebd400fe391f822f..6163776152b534a6f8074a625ae463ade0f86131 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -145,10 +145,8 @@ void grpc_init(void) { grpc_register_tracer("server_channel", &grpc_server_channel_trace); grpc_register_tracer("bdp_estimator", &grpc_bdp_estimator_trace); // Default pluck trace to 1 - grpc_cq_pluck_trace = 1; grpc_register_tracer("queue_timeout", &grpc_cq_event_timeout_trace); // Default timeout trace to 1 - grpc_cq_event_timeout_trace = 1; grpc_register_tracer("op_failure", &grpc_trace_operation_failures); grpc_register_tracer("resource_quota", &grpc_resource_quota_trace); grpc_register_tracer("call_error", &grpc_call_error_trace); @@ -173,6 +171,7 @@ void grpc_init(void) { grpc_tracer_init("GRPC_TRACE"); /* no more changes to channel init pipelines */ grpc_channel_init_finalize(); + grpc_iomgr_start(); } gpr_mu_unlock(&g_init_mu); GRPC_API_TRACE("grpc_init(void)", 0, ()); diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c index 934ca0431a6f2349232712fc4b8464c6201494b9..560229e892cdcf4a005256e24e7ae56f66ca726a 100644 --- a/src/core/lib/surface/server.c +++ b/src/core/lib/surface/server.c @@ -73,7 +73,7 @@ typedef struct registered_method registered_method; typedef enum { BATCH_CALL, REGISTERED_CALL } requested_call_type; -int grpc_server_channel_trace = 0; +grpc_tracer_flag grpc_server_channel_trace = GRPC_TRACER_INITIALIZER(false); typedef struct requested_call { requested_call_type type; @@ -408,7 +408,7 @@ static void server_delete(grpc_exec_ctx *exec_ctx, grpc_server *server) { request_matcher_destroy(&server->unregistered_request_matcher); } for (i = 0; i < server->cq_count; i++) { - GRPC_CQ_INTERNAL_UNREF(server->cqs[i], "server"); + GRPC_CQ_INTERNAL_UNREF(exec_ctx, server->cqs[i], "server"); if (server->started) { gpr_stack_lockfree_destroy(server->request_freelist_per_cq[i]); gpr_free(server->requested_calls_per_cq[i]); @@ -456,7 +456,7 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand, grpc_closure_init(&chand->finish_destroy_channel_closure, finish_destroy_channel, chand, grpc_schedule_on_exec_ctx); - if (grpc_server_channel_trace && error != GRPC_ERROR_NONE) { + if (GRPC_TRACER_ON(grpc_server_channel_trace) && error != GRPC_ERROR_NONE) { const char *msg = grpc_error_string(error); gpr_log(GPR_INFO, "Disconnected client: %s", msg); } diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h index a85d9f4964cc80f84652aefc31209d93963e430f..cd2fca0fe02d3158a09eaefeff9262e5c3ef83ce 100644 --- a/src/core/lib/surface/server.h +++ b/src/core/lib/surface/server.h @@ -36,12 +36,13 @@ #include <grpc/grpc.h> #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/debug/trace.h" #include "src/core/lib/transport/transport.h" extern const grpc_channel_filter grpc_server_top_filter; /** Lightweight tracing of server channel state */ -extern int grpc_server_channel_trace; +extern grpc_tracer_flag grpc_server_channel_trace; /* Add a listener to the server: when the server starts, it will call start, and when it shuts down, it will call destroy */ diff --git a/src/core/lib/transport/bdp_estimator.c b/src/core/lib/transport/bdp_estimator.c index e1483677fd307bb2fae5d28474fa7e46d0bd6b6d..da8019d98bddc499b9cdca53ae450f5b6ba77a75 100644 --- a/src/core/lib/transport/bdp_estimator.c +++ b/src/core/lib/transport/bdp_estimator.c @@ -38,12 +38,13 @@ #include <grpc/support/log.h> #include <grpc/support/useful.h> -int grpc_bdp_estimator_trace = 0; +grpc_tracer_flag grpc_bdp_estimator_trace = GRPC_TRACER_INITIALIZER(false); void grpc_bdp_estimator_init(grpc_bdp_estimator *estimator, const char *name) { estimator->estimate = 65536; estimator->ping_state = GRPC_BDP_PING_UNSCHEDULED; estimator->name = name; + estimator->bw_est = 0; } bool grpc_bdp_estimator_get_estimate(grpc_bdp_estimator *estimator, @@ -67,7 +68,7 @@ bool grpc_bdp_estimator_add_incoming_bytes(grpc_bdp_estimator *estimator, } void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator) { - if (grpc_bdp_estimator_trace) { + if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, estimator->name, estimator->accumulator, estimator->estimate); } @@ -77,24 +78,34 @@ void grpc_bdp_estimator_schedule_ping(grpc_bdp_estimator *estimator) { } void grpc_bdp_estimator_start_ping(grpc_bdp_estimator *estimator) { - if (grpc_bdp_estimator_trace) { + if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, estimator->name, estimator->accumulator, estimator->estimate); } GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_SCHEDULED); estimator->ping_state = GRPC_BDP_PING_STARTED; estimator->accumulator = 0; + estimator->ping_start_time = gpr_now(GPR_CLOCK_MONOTONIC); } void grpc_bdp_estimator_complete_ping(grpc_bdp_estimator *estimator) { - if (grpc_bdp_estimator_trace) { - gpr_log(GPR_DEBUG, "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64, - estimator->name, estimator->accumulator, estimator->estimate); + gpr_timespec dt_ts = + gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), estimator->ping_start_time); + double dt = (double)dt_ts.tv_sec + 1e-9 * (double)dt_ts.tv_nsec; + double bw = dt > 0 ? ((double)estimator->accumulator / dt) : 0; + if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { + gpr_log(GPR_DEBUG, "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64 + " dt=%lf bw=%lfMbs bw_est=%lfMbs", + estimator->name, estimator->accumulator, estimator->estimate, dt, + bw / 125000.0, estimator->bw_est / 125000.0); } GPR_ASSERT(estimator->ping_state == GRPC_BDP_PING_STARTED); - if (estimator->accumulator > 2 * estimator->estimate / 3) { - estimator->estimate *= 2; - if (grpc_bdp_estimator_trace) { + if (estimator->accumulator > 2 * estimator->estimate / 3 && + bw > estimator->bw_est) { + estimator->estimate = + GPR_MAX(estimator->accumulator, estimator->estimate * 2); + estimator->bw_est = bw; + if (GRPC_TRACER_ON(grpc_bdp_estimator_trace)) { gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64, estimator->name, estimator->estimate); } diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h index df8d1f6fc0f12cff0f45e3b104fc472af901cc1a..135376edd7f81ceca9bd55f6abe8e37bcf4febb1 100644 --- a/src/core/lib/transport/bdp_estimator.h +++ b/src/core/lib/transport/bdp_estimator.h @@ -34,13 +34,15 @@ #ifndef GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H #define GRPC_CORE_LIB_TRANSPORT_BDP_ESTIMATOR_H +#include <grpc/support/time.h> #include <stdbool.h> #include <stdint.h> +#include "src/core/lib/debug/trace.h" #define GRPC_BDP_SAMPLES 16 #define GRPC_BDP_MIN_SAMPLES_FOR_ESTIMATE 3 -extern int grpc_bdp_estimator_trace; +extern grpc_tracer_flag grpc_bdp_estimator_trace; typedef enum { GRPC_BDP_PING_UNSCHEDULED, @@ -52,6 +54,8 @@ typedef struct grpc_bdp_estimator { grpc_bdp_estimator_ping_state ping_state; int64_t accumulator; int64_t estimate; + gpr_timespec ping_start_time; + double bw_est; const char *name; } grpc_bdp_estimator; diff --git a/src/core/lib/transport/connectivity_state.c b/src/core/lib/transport/connectivity_state.c index 3757b252676850f460f9474bf1daf6742270f8f2..e30cd523fa44f951b08ad8484e06c64312d059a6 100644 --- a/src/core/lib/transport/connectivity_state.c +++ b/src/core/lib/transport/connectivity_state.c @@ -39,7 +39,7 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> -int grpc_connectivity_state_trace = 0; +grpc_tracer_flag grpc_connectivity_state_trace = GRPC_TRACER_INITIALIZER(false); const char *grpc_connectivity_state_name(grpc_connectivity_state state) { switch (state) { @@ -94,7 +94,7 @@ grpc_connectivity_state grpc_connectivity_state_check( grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); - if (grpc_connectivity_state_trace) { + if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name, grpc_connectivity_state_name(cur)); } @@ -106,7 +106,7 @@ grpc_connectivity_state grpc_connectivity_state_get( grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); - if (grpc_connectivity_state_trace) { + if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name, grpc_connectivity_state_name(cur)); } @@ -127,7 +127,7 @@ bool grpc_connectivity_state_notify_on_state_change( grpc_connectivity_state cur = (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); - if (grpc_connectivity_state_trace) { + if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { if (current == NULL) { gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker, tracker->name, notify); @@ -180,7 +180,7 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, (grpc_connectivity_state)gpr_atm_no_barrier_load( &tracker->current_state_atm); grpc_connectivity_state_watcher *w; - if (grpc_connectivity_state_trace) { + if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { const char *error_string = grpc_error_string(error); gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker, tracker->name, grpc_connectivity_state_name(cur), @@ -208,7 +208,7 @@ void grpc_connectivity_state_set(grpc_exec_ctx *exec_ctx, while ((w = tracker->watchers) != NULL) { *w->current = state; tracker->watchers = w->next; - if (grpc_connectivity_state_trace) { + if (GRPC_TRACER_ON(grpc_connectivity_state_trace)) { gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify); } diff --git a/src/core/lib/transport/connectivity_state.h b/src/core/lib/transport/connectivity_state.h index c9604c34dda6dd26a9e187decb0c2b344c628616..cdc2930c11cc375ea73f3596f5769960d88224d0 100644 --- a/src/core/lib/transport/connectivity_state.h +++ b/src/core/lib/transport/connectivity_state.h @@ -35,6 +35,7 @@ #define GRPC_CORE_LIB_TRANSPORT_CONNECTIVITY_STATE_H #include <grpc/grpc.h> +#include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/exec_ctx.h" typedef struct grpc_connectivity_state_watcher { @@ -57,7 +58,7 @@ typedef struct { char *name; } grpc_connectivity_state_tracker; -extern int grpc_connectivity_state_trace; +extern grpc_tracer_flag grpc_connectivity_state_trace; /** enum --> string conversion */ const char *grpc_connectivity_state_name(grpc_connectivity_state state); diff --git a/src/core/tsi/fake_transport_security.c b/src/core/tsi/fake_transport_security.c index 1836beefc421f6c213010bd0b073f779ff9f07f1..4925d19f96e2d6f0c64e4d1916be424371c68adb 100644 --- a/src/core/tsi/fake_transport_security.c +++ b/src/core/tsi/fake_transport_security.c @@ -396,7 +396,7 @@ static tsi_result fake_handshaker_get_bytes_to_send_to_peer( if (next_message_to_send > TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { next_message_to_send = TSI_FAKE_HANDSHAKE_MESSAGE_MAX; } - if (tsi_tracing_enabled) { + if (GRPC_TRACER_ON(tsi_tracing_enabled)) { gpr_log(GPR_INFO, "%s prepared %s.", impl->is_client ? "Client" : "Server", tsi_fake_handshake_message_to_string(impl->next_message_to_send)); @@ -408,7 +408,7 @@ static tsi_result fake_handshaker_get_bytes_to_send_to_peer( if (!impl->is_client && impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { /* We're done. */ - if (tsi_tracing_enabled) { + if (GRPC_TRACER_ON(tsi_tracing_enabled)) { gpr_log(GPR_INFO, "Server is done."); } impl->result = TSI_OK; @@ -445,7 +445,7 @@ static tsi_result fake_handshaker_process_bytes_from_peer( tsi_fake_handshake_message_to_string(received_msg), tsi_fake_handshake_message_to_string(expected_msg)); } - if (tsi_tracing_enabled) { + if (GRPC_TRACER_ON(tsi_tracing_enabled)) { gpr_log(GPR_INFO, "%s received %s.", impl->is_client ? "Client" : "Server", tsi_fake_handshake_message_to_string(received_msg)); } @@ -453,7 +453,7 @@ static tsi_result fake_handshaker_process_bytes_from_peer( impl->needs_incoming_message = 0; if (impl->next_message_to_send == TSI_FAKE_HANDSHAKE_MESSAGE_MAX) { /* We're done. */ - if (tsi_tracing_enabled) { + if (GRPC_TRACER_ON(tsi_tracing_enabled)) { gpr_log(GPR_INFO, "%s is done.", impl->is_client ? "Client" : "Server"); } impl->result = TSI_OK; diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c index e1d634a1fa445debefdab856fe34d105ebe1244e..59fd2b1c93a7ee1e4eb8d1c44cc9123b79c36c7f 100644 --- a/src/core/tsi/ssl_transport_security.c +++ b/src/core/tsi/ssl_transport_security.c @@ -180,7 +180,7 @@ static const char *ssl_error_string(int error) { /* TODO(jboeuf): Remove when we are past the debugging phase with this code. */ static void ssl_log_where_info(const SSL *ssl, int where, int flag, const char *msg) { - if ((where & flag) && tsi_tracing_enabled) { + if ((where & flag) && GRPC_TRACER_ON(tsi_tracing_enabled)) { gpr_log(GPR_INFO, "%20.20s - %30.30s - %5.10s", msg, SSL_state_string_long(ssl), SSL_state_string(ssl)); } diff --git a/src/core/tsi/transport_security.c b/src/core/tsi/transport_security.c index b11c00c43c43434c21012fceed7f623ad59902f8..4efcf8f43d8668db95ef74419094f14d9280e659 100644 --- a/src/core/tsi/transport_security.c +++ b/src/core/tsi/transport_security.c @@ -41,7 +41,7 @@ /* --- Tracing. --- */ -int tsi_tracing_enabled = 0; +grpc_tracer_flag tsi_tracing_enabled = GRPC_TRACER_INITIALIZER(false); /* --- tsi_result common implementation. --- */ diff --git a/src/core/tsi/transport_security.h b/src/core/tsi/transport_security.h index a4c9cbc00111e68238cb87ac38968f694796b2b2..2422f9207674cceff710b81f80757989c1ce379c 100644 --- a/src/core/tsi/transport_security.h +++ b/src/core/tsi/transport_security.h @@ -36,13 +36,14 @@ #include <stdbool.h> +#include "src/core/lib/debug/trace.h" #include "src/core/tsi/transport_security_interface.h" #ifdef __cplusplus extern "C" { #endif -extern int tsi_tracing_enabled; +extern grpc_tracer_flag tsi_tracing_enabled; /* Base for tsi_frame_protector implementations. See transport_security_interface.h for documentation. */ diff --git a/src/core/tsi/transport_security_interface.h b/src/core/tsi/transport_security_interface.h index f2112b62b6764e29dec1bcaee1b1425d50636d4c..8a3fff6a17064bebc6fff681d4605ca25ef72a21 100644 --- a/src/core/tsi/transport_security_interface.h +++ b/src/core/tsi/transport_security_interface.h @@ -37,6 +37,8 @@ #include <stdint.h> #include <stdlib.h> +#include "src/core/lib/debug/trace.h" + #ifdef __cplusplus extern "C" { #endif @@ -73,8 +75,7 @@ const char *tsi_result_to_string(tsi_result result); /* --- tsi tracing --- */ -/* Set this early to avoid races */ -extern int tsi_tracing_enabled; +extern grpc_tracer_flag tsi_tracing_enabled; /* --- tsi_frame_protector object --- diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc index f679a339456920d95f9b9e57e7268f98291b33b2..2b484c0a08ef07b59e23be3bcc4656306a90db02 100644 --- a/src/cpp/common/core_codegen.cc +++ b/src/cpp/common/core_codegen.cc @@ -134,6 +134,12 @@ grpc_byte_buffer* CoreCodegen::grpc_raw_byte_buffer_create(grpc_slice* slice, return ::grpc_raw_byte_buffer_create(slice, nslices); } +grpc_slice CoreCodegen::grpc_slice_new_with_user_data(void* p, size_t len, + void (*destroy)(void*), + void* user_data) { + return ::grpc_slice_new_with_user_data(p, len, destroy, user_data); +} + grpc_slice CoreCodegen::grpc_empty_slice() { return ::grpc_empty_slice(); } grpc_slice CoreCodegen::grpc_slice_malloc(size_t length) { @@ -144,10 +150,18 @@ void CoreCodegen::grpc_slice_unref(grpc_slice slice) { ::grpc_slice_unref(slice); } +grpc_slice CoreCodegen::grpc_slice_ref(grpc_slice slice) { + return ::grpc_slice_ref(slice); +} + grpc_slice CoreCodegen::grpc_slice_split_tail(grpc_slice* s, size_t split) { return ::grpc_slice_split_tail(s, split); } +grpc_slice CoreCodegen::grpc_slice_split_head(grpc_slice* s, size_t split) { + return ::grpc_slice_split_head(s, split); +} + grpc_slice CoreCodegen::grpc_slice_from_static_buffer(const void* buffer, size_t length) { return ::grpc_slice_from_static_buffer(buffer, length); diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index b4d6961db890fdaa944e67d62ab5d8479083c633..7c93bb86838b4114db2cf243aacd614895db40ac 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -521,7 +521,7 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { if (health_check_service_ == nullptr && !health_check_service_disabled_ && DefaultHealthCheckServiceEnabled()) { if (sync_server_cqs_->empty()) { - gpr_log(GPR_ERROR, + gpr_log(GPR_INFO, "Default health check service disabled at async-only server."); } else { auto* default_hc_service = new DefaultHealthCheckService; @@ -686,6 +686,7 @@ bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag, StringFromCopiedSlice(call_details_.method); static_cast<GenericServerContext*>(context_)->host_ = StringFromCopiedSlice(call_details_.host); + context_->deadline_ = call_details_.deadline; } grpc_slice_unref(call_details_.method); grpc_slice_unref(call_details_.host); diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include index 6af2af10bd00cc6d67c0ff88968acfc6b61c2d01..8388bfd9cca5d8db703d06b0455da62985622d84 100755 --- a/src/csharp/Grpc.Core/Version.csproj.include +++ b/src/csharp/Grpc.Core/Version.csproj.include @@ -2,6 +2,6 @@ <Project> <PropertyGroup> <GrpcCsharpVersion>1.4.0-dev</GrpcCsharpVersion> - <GoogleProtobufVersion>3.2.0</GoogleProtobufVersion> + <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion> </PropertyGroup> </Project> diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc index e193e82179aa12af62ccf2903bf007104173b613..c444ad0b7b12aae153ee24ac715b65ee39b87bf8 100644 --- a/src/node/ext/node_grpc.cc +++ b/src/node/ext/node_grpc.cc @@ -85,98 +85,6 @@ logger_state grpc_logger_state; static char *pem_root_certs = NULL; -void InitStatusConstants(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> status = Nan::New<Object>(); - Nan::Set(exports, Nan::New("status").ToLocalChecked(), status); - Local<Value> OK(Nan::New<Uint32, uint32_t>(GRPC_STATUS_OK)); - Nan::Set(status, Nan::New("OK").ToLocalChecked(), OK); - Local<Value> CANCELLED(Nan::New<Uint32, uint32_t>(GRPC_STATUS_CANCELLED)); - Nan::Set(status, Nan::New("CANCELLED").ToLocalChecked(), CANCELLED); - Local<Value> UNKNOWN(Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNKNOWN)); - Nan::Set(status, Nan::New("UNKNOWN").ToLocalChecked(), UNKNOWN); - Local<Value> INVALID_ARGUMENT( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_INVALID_ARGUMENT)); - Nan::Set(status, Nan::New("INVALID_ARGUMENT").ToLocalChecked(), - INVALID_ARGUMENT); - Local<Value> DEADLINE_EXCEEDED( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_DEADLINE_EXCEEDED)); - Nan::Set(status, Nan::New("DEADLINE_EXCEEDED").ToLocalChecked(), - DEADLINE_EXCEEDED); - Local<Value> NOT_FOUND(Nan::New<Uint32, uint32_t>(GRPC_STATUS_NOT_FOUND)); - Nan::Set(status, Nan::New("NOT_FOUND").ToLocalChecked(), NOT_FOUND); - Local<Value> ALREADY_EXISTS( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_ALREADY_EXISTS)); - Nan::Set(status, Nan::New("ALREADY_EXISTS").ToLocalChecked(), ALREADY_EXISTS); - Local<Value> PERMISSION_DENIED( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_PERMISSION_DENIED)); - Nan::Set(status, Nan::New("PERMISSION_DENIED").ToLocalChecked(), - PERMISSION_DENIED); - Local<Value> UNAUTHENTICATED( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNAUTHENTICATED)); - Nan::Set(status, Nan::New("UNAUTHENTICATED").ToLocalChecked(), - UNAUTHENTICATED); - Local<Value> RESOURCE_EXHAUSTED( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_RESOURCE_EXHAUSTED)); - Nan::Set(status, Nan::New("RESOURCE_EXHAUSTED").ToLocalChecked(), - RESOURCE_EXHAUSTED); - Local<Value> FAILED_PRECONDITION( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_FAILED_PRECONDITION)); - Nan::Set(status, Nan::New("FAILED_PRECONDITION").ToLocalChecked(), - FAILED_PRECONDITION); - Local<Value> ABORTED(Nan::New<Uint32, uint32_t>(GRPC_STATUS_ABORTED)); - Nan::Set(status, Nan::New("ABORTED").ToLocalChecked(), ABORTED); - Local<Value> OUT_OF_RANGE( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_OUT_OF_RANGE)); - Nan::Set(status, Nan::New("OUT_OF_RANGE").ToLocalChecked(), OUT_OF_RANGE); - Local<Value> UNIMPLEMENTED( - Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNIMPLEMENTED)); - Nan::Set(status, Nan::New("UNIMPLEMENTED").ToLocalChecked(), UNIMPLEMENTED); - Local<Value> INTERNAL(Nan::New<Uint32, uint32_t>(GRPC_STATUS_INTERNAL)); - Nan::Set(status, Nan::New("INTERNAL").ToLocalChecked(), INTERNAL); - Local<Value> UNAVAILABLE(Nan::New<Uint32, uint32_t>(GRPC_STATUS_UNAVAILABLE)); - Nan::Set(status, Nan::New("UNAVAILABLE").ToLocalChecked(), UNAVAILABLE); - Local<Value> DATA_LOSS(Nan::New<Uint32, uint32_t>(GRPC_STATUS_DATA_LOSS)); - Nan::Set(status, Nan::New("DATA_LOSS").ToLocalChecked(), DATA_LOSS); -} - -void InitCallErrorConstants(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> call_error = Nan::New<Object>(); - Nan::Set(exports, Nan::New("callError").ToLocalChecked(), call_error); - Local<Value> OK(Nan::New<Uint32, uint32_t>(GRPC_CALL_OK)); - Nan::Set(call_error, Nan::New("OK").ToLocalChecked(), OK); - Local<Value> CALL_ERROR(Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR)); - Nan::Set(call_error, Nan::New("ERROR").ToLocalChecked(), CALL_ERROR); - Local<Value> NOT_ON_SERVER( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_ON_SERVER)); - Nan::Set(call_error, Nan::New("NOT_ON_SERVER").ToLocalChecked(), - NOT_ON_SERVER); - Local<Value> NOT_ON_CLIENT( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_ON_CLIENT)); - Nan::Set(call_error, Nan::New("NOT_ON_CLIENT").ToLocalChecked(), - NOT_ON_CLIENT); - Local<Value> ALREADY_INVOKED( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_ALREADY_INVOKED)); - Nan::Set(call_error, Nan::New("ALREADY_INVOKED").ToLocalChecked(), - ALREADY_INVOKED); - Local<Value> NOT_INVOKED( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_INVOKED)); - Nan::Set(call_error, Nan::New("NOT_INVOKED").ToLocalChecked(), NOT_INVOKED); - Local<Value> ALREADY_FINISHED( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_ALREADY_FINISHED)); - Nan::Set(call_error, Nan::New("ALREADY_FINISHED").ToLocalChecked(), - ALREADY_FINISHED); - Local<Value> TOO_MANY_OPERATIONS( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS)); - Nan::Set(call_error, Nan::New("TOO_MANY_OPERATIONS").ToLocalChecked(), - TOO_MANY_OPERATIONS); - Local<Value> INVALID_FLAGS( - Nan::New<Uint32, uint32_t>(GRPC_CALL_ERROR_INVALID_FLAGS)); - Nan::Set(call_error, Nan::New("INVALID_FLAGS").ToLocalChecked(), - INVALID_FLAGS); -} - void InitOpTypeConstants(Local<Object> exports) { Nan::HandleScope scope; Local<Object> op_type = Nan::New<Object>(); @@ -211,27 +119,6 @@ void InitOpTypeConstants(Local<Object> exports) { RECV_CLOSE_ON_SERVER); } -void InitPropagateConstants(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> propagate = Nan::New<Object>(); - Nan::Set(exports, Nan::New("propagate").ToLocalChecked(), propagate); - Local<Value> DEADLINE(Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_DEADLINE)); - Nan::Set(propagate, Nan::New("DEADLINE").ToLocalChecked(), DEADLINE); - Local<Value> CENSUS_STATS_CONTEXT( - Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)); - Nan::Set(propagate, Nan::New("CENSUS_STATS_CONTEXT").ToLocalChecked(), - CENSUS_STATS_CONTEXT); - Local<Value> CENSUS_TRACING_CONTEXT( - Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT)); - Nan::Set(propagate, Nan::New("CENSUS_TRACING_CONTEXT").ToLocalChecked(), - CENSUS_TRACING_CONTEXT); - Local<Value> CANCELLATION( - Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_CANCELLATION)); - Nan::Set(propagate, Nan::New("CANCELLATION").ToLocalChecked(), CANCELLATION); - Local<Value> DEFAULTS(Nan::New<Uint32, uint32_t>(GRPC_PROPAGATE_DEFAULTS)); - Nan::Set(propagate, Nan::New("DEFAULTS").ToLocalChecked(), DEFAULTS); -} - void InitConnectivityStateConstants(Local<Object> exports) { Nan::HandleScope scope; Local<Object> channel_state = Nan::New<Object>(); @@ -252,28 +139,6 @@ void InitConnectivityStateConstants(Local<Object> exports) { FATAL_FAILURE); } -void InitWriteFlags(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> write_flags = Nan::New<Object>(); - Nan::Set(exports, Nan::New("writeFlags").ToLocalChecked(), write_flags); - Local<Value> BUFFER_HINT(Nan::New<Uint32, uint32_t>(GRPC_WRITE_BUFFER_HINT)); - Nan::Set(write_flags, Nan::New("BUFFER_HINT").ToLocalChecked(), BUFFER_HINT); - Local<Value> NO_COMPRESS(Nan::New<Uint32, uint32_t>(GRPC_WRITE_NO_COMPRESS)); - Nan::Set(write_flags, Nan::New("NO_COMPRESS").ToLocalChecked(), NO_COMPRESS); -} - -void InitLogConstants(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> log_verbosity = Nan::New<Object>(); - Nan::Set(exports, Nan::New("logVerbosity").ToLocalChecked(), log_verbosity); - Local<Value> LOG_DEBUG(Nan::New<Uint32, uint32_t>(GPR_LOG_SEVERITY_DEBUG)); - Nan::Set(log_verbosity, Nan::New("DEBUG").ToLocalChecked(), LOG_DEBUG); - Local<Value> LOG_INFO(Nan::New<Uint32, uint32_t>(GPR_LOG_SEVERITY_INFO)); - Nan::Set(log_verbosity, Nan::New("INFO").ToLocalChecked(), LOG_INFO); - Local<Value> LOG_ERROR(Nan::New<Uint32, uint32_t>(GPR_LOG_SEVERITY_ERROR)); - Nan::Set(log_verbosity, Nan::New("ERROR").ToLocalChecked(), LOG_ERROR); -} - NAN_METHOD(MetadataKeyIsLegal) { if (!info[0]->IsString()) { return Nan::ThrowTypeError("headerKeyIsLegal's argument must be a string"); @@ -421,13 +286,8 @@ void init(Local<Object> exports) { grpc_set_ssl_roots_override_callback(get_ssl_roots_override); init_logger(); - InitStatusConstants(exports); - InitCallErrorConstants(exports); InitOpTypeConstants(exports); - InitPropagateConstants(exports); InitConnectivityStateConstants(exports); - InitWriteFlags(exports); - InitLogConstants(exports); grpc_pollset_work_run_loop = 0; diff --git a/src/node/index.js b/src/node/index.js index 071bfd7927bab798c2bf0920355be32c54cd7242..0da3440eb77241fb7a2162817036d8e29c054d5d 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -31,6 +31,10 @@ * */ +/** + * @module + */ + 'use strict'; var path = require('path'); @@ -55,6 +59,8 @@ var grpc = require('./src/grpc_extension'); var protobuf_js_5_common = require('./src/protobuf_js_5_common'); var protobuf_js_6_common = require('./src/protobuf_js_6_common'); +var constants = require('./src/constants.js'); + grpc.setDefaultRootsPem(fs.readFileSync(SSL_ROOTS_PATH, 'ascii')); /** @@ -208,27 +214,27 @@ exports.Metadata = Metadata; /** * Status name to code number mapping */ -exports.status = grpc.status; +exports.status = constants.status; /** * Propagate flag name to number mapping */ -exports.propagate = grpc.propagate; +exports.propagate = constants.propagate; /** * Call error name to code number mapping */ -exports.callError = grpc.callError; +exports.callError = constants.callError; /** * Write flag name to code number mapping */ -exports.writeFlags = grpc.writeFlags; +exports.writeFlags = constants.writeFlags; /** * Log verbosity setting name to code number mapping */ -exports.logVerbosity = grpc.logVerbosity; +exports.logVerbosity = constants.logVerbosity; /** * Credentials factories @@ -256,5 +262,10 @@ exports.getClientChannel = client.getClientChannel; exports.waitForClientReady = client.waitForClientReady; exports.closeClient = function closeClient(client_obj) { - client.getClientChannel(client_obj).close(); + client.Client.prototype.close.apply(client_obj); }; + +/** + * @see module:src/client.Client + */ +exports.Client = client.Client; diff --git a/src/node/jsdoc_conf.json b/src/node/jsdoc_conf.json index c3a0174f0e3f1424314cd9ef82c41ea1530dc035..2d967753c1e2cd52030aba4a033c113d6641288d 100644 --- a/src/node/jsdoc_conf.json +++ b/src/node/jsdoc_conf.json @@ -11,7 +11,7 @@ "package": "package.json", "readme": "src/node/README.md" }, - "plugins": [], + "plugins": ["plugins/markdown"], "templates": { "cleverLinks": false, "monospaceLinks": false, diff --git a/src/node/src/client.js b/src/node/src/client.js index 1aaf35c16cbc918bdd220e3ba04b2832817576db..16fe06a54d2c7c0bcfc62fdb01a22cdf71d00f64 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -37,7 +37,7 @@ * This module contains the factory method for creating Client classes, and the * method calling code for all types of methods. * - * For example, to create a client and call a method on it: + * @example <caption>Create a client and call a method on it</caption> * * var proto_obj = grpc.load(proto_file_path); * var Client = proto_obj.package.subpackage.ServiceName; @@ -58,6 +58,8 @@ var common = require('./common'); var Metadata = require('./metadata'); +var constants = require('./constants'); + var EventEmitter = require('events').EventEmitter; var stream = require('stream'); @@ -68,14 +70,33 @@ var Duplex = stream.Duplex; var util = require('util'); var version = require('../../../package.json').version; +util.inherits(ClientUnaryCall, EventEmitter); + +/** + * An EventEmitter. Used for unary calls + * @constructor + * @extends external:EventEmitter + * @param {grpc.Call} call The call object associated with the request + */ +function ClientUnaryCall(call) { + EventEmitter.call(this); + this.call = call; +} + util.inherits(ClientWritableStream, Writable); /** * A stream that the client can write to. Used for calls that are streaming from * the client side. * @constructor + * @extends external:Writable + * @borrows module:src/client~ClientUnaryCall#cancel as + * module:src/client~ClientWritableStream#cancel + * @borrows module:src/client~ClientUnaryCall#getPeer as + * module:src/client~ClientWritableStream#getPeer * @param {grpc.Call} call The call object to send data with - * @param {function(*):Buffer=} serialize Serialization function for writes. + * @param {module:src/common~serialize=} [serialize=identity] Serialization + * function for writes. */ function ClientWritableStream(call, serialize) { Writable.call(this, {objectMode: true}); @@ -108,7 +129,8 @@ function _write(chunk, encoding, callback) { but passing an object that causes a serialization failure is a misuse of the API anyway, so that's OK. The primary purpose here is to give the programmer a useful error and to stop the stream properly */ - this.call.cancelWithStatus(grpc.status.INTERNAL, 'Serialization failure'); + this.call.cancelWithStatus(constants.status.INTERNAL, + 'Serialization failure'); callback(e); } if (_.isFinite(encoding)) { @@ -134,8 +156,14 @@ util.inherits(ClientReadableStream, Readable); * A stream that the client can read from. Used for calls that are streaming * from the server side. * @constructor + * @extends external:Readable + * @borrows module:src/client~ClientUnaryCall#cancel as + * module:src/client~ClientReadableStream#cancel + * @borrows module:src/client~ClientUnaryCall#getPeer as + * module:src/client~ClientReadableStream#getPeer * @param {grpc.Call} call The call object to read data with - * @param {function(Buffer):*=} deserialize Deserialization function for reads + * @param {module:src/common~deserialize=} [deserialize=identity] + * Deserialization function for reads */ function ClientReadableStream(call, deserialize) { Readable.call(this, {objectMode: true}); @@ -155,13 +183,14 @@ function ClientReadableStream(call, deserialize) { * parameter indicates that the call should end with that status. status * defaults to OK if not provided. * @param {Object!} status The status that the call should end with + * @access private */ function _readsDone(status) { /* jshint validthis: true */ if (!status) { - status = {code: grpc.status.OK, details: 'OK'}; + status = {code: constants.status.OK, details: 'OK'}; } - if (status.code !== grpc.status.OK) { + if (status.code !== constants.status.OK) { this.call.cancelWithStatus(status.code, status.details); } this.finished = true; @@ -173,6 +202,7 @@ ClientReadableStream.prototype._readsDone = _readsDone; /** * Called to indicate that we have received a status from the server. + * @access private */ function _receiveStatus(status) { /* jshint validthis: true */ @@ -185,17 +215,18 @@ ClientReadableStream.prototype._receiveStatus = _receiveStatus; /** * If we have both processed all incoming messages and received the status from * the server, emit the status. Otherwise, do nothing. + * @access private */ function _emitStatusIfDone() { /* jshint validthis: true */ var status; if (this.read_status && this.received_status) { - if (this.read_status.code !== grpc.status.OK) { + if (this.read_status.code !== constants.status.OK) { status = this.read_status; } else { status = this.received_status; } - if (status.code === grpc.status.OK) { + if (status.code === constants.status.OK) { this.push(null); } else { var error = new Error(status.details); @@ -234,7 +265,7 @@ function _read(size) { try { deserialized = self.deserialize(data); } catch (e) { - self._readsDone({code: grpc.status.INTERNAL, + self._readsDone({code: constants.status.INTERNAL, details: 'Failed to parse server response'}); return; } @@ -270,10 +301,16 @@ util.inherits(ClientDuplexStream, Duplex); * A stream that the client can read from or write to. Used for calls with * duplex streaming. * @constructor + * @extends external:Duplex + * @borrows module:src/client~ClientUnaryCall#cancel as + * module:src/client~ClientDuplexStream#cancel + * @borrows module:src/client~ClientUnaryCall#getPeer as + * module:src/client~ClientDuplexStream#getPeer * @param {grpc.Call} call Call object to proxy - * @param {function(*):Buffer=} serialize Serialization function for requests - * @param {function(Buffer):*=} deserialize Deserialization function for - * responses + * @param {module:src/common~serialize=} [serialize=identity] Serialization + * function for requests + * @param {module:src/common~deserialize=} [deserialize=identity] + * Deserialization function for responses */ function ClientDuplexStream(call, serialize, deserialize) { Duplex.call(this, {objectMode: true}); @@ -300,12 +337,14 @@ ClientDuplexStream.prototype._write = _write; /** * Cancel the ongoing call + * @alias module:src/client~ClientUnaryCall#cancel */ function cancel() { /* jshint validthis: true */ this.call.cancel(); } +ClientUnaryCall.prototype.cancel = cancel; ClientReadableStream.prototype.cancel = cancel; ClientWritableStream.prototype.cancel = cancel; ClientDuplexStream.prototype.cancel = cancel; @@ -313,21 +352,49 @@ ClientDuplexStream.prototype.cancel = cancel; /** * Get the endpoint this call/stream is connected to. * @return {string} The URI of the endpoint + * @alias module:src/client~ClientUnaryCall#getPeer */ function getPeer() { /* jshint validthis: true */ return this.call.getPeer(); } +ClientUnaryCall.prototype.getPeer = getPeer; ClientReadableStream.prototype.getPeer = getPeer; ClientWritableStream.prototype.getPeer = getPeer; ClientDuplexStream.prototype.getPeer = getPeer; +/** + * Any client call type + * @typedef {(ClientUnaryCall|ClientReadableStream| + * ClientWritableStream|ClientDuplexStream)} + * module:src/client~Call + */ + +/** + * Options that can be set on a call. + * @typedef {Object} module:src/client~CallOptions + * @property {(date|number)} deadline The deadline for the entire call to + * complete. A value of Infinity indicates that no deadline should be set. + * @property {(string)} host Server hostname to set on the call. Only meaningful + * if different from the server address used to construct the client. + * @property {module:src/client~Call} parent Parent call. Used in servers when + * making a call as part of the process of handling a call. Used to + * propagate some information automatically, as specified by + * propagate_flags. + * @property {number} propagate_flags Indicates which properties of a parent + * call should propagate to this call. Bitwise combination of flags in + * [grpc.propagate]{@link module:index.propagate}. + * @property {module:src/credentials~CallCredentials} credentials The + * credentials that should be used to make this particular call. + */ + /** * Get a call object built with the provided options. Keys for options are * 'deadline', which takes a date or number, and 'host', which takes a string * and overrides the hostname to connect to. - * @param {Object} options Options map. + * @access private + * @param {module:src/client~CallOptions=} options Options object. */ function getCall(channel, method, options) { var deadline; @@ -354,315 +421,380 @@ function getCall(channel, method, options) { } /** - * Get a function that can make unary requests to the specified method. - * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeUnaryRequest + * A generic gRPC client. Primarily useful as a base class for generated clients + * @alias module:src/client.Client + * @constructor + * @param {string} address Server address to connect to + * @param {module:src/credentials~ChannelCredentials} credentials Credentials to + * use to connect to the server + * @param {Object} options Options to apply to channel creation */ -function makeUnaryRequestFunction(method, serialize, deserialize) { - /** - * Make a unary request with this method on the given channel with the given - * argument, callback, etc. - * @this {Client} Client object. Must have a channel member. - * @param {*} argument The argument to the call. Should be serializable with - * serialize - * @param {Metadata=} metadata Metadata to add to the call - * @param {Object=} options Options map - * @param {function(?Error, value=)} callback The callback to for when the - * response is received - * @return {EventEmitter} An event emitter for stream related events +var Client = exports.Client = function Client(address, credentials, options) { + if (!options) { + options = {}; + } + /* Append the grpc-node user agent string after the application user agent + * string, and put the combination at the beginning of the user agent string */ - function makeUnaryRequest(argument, metadata, options, callback) { - /* jshint validthis: true */ - /* While the arguments are listed in the function signature, those variables - * are not used directly. Instead, ArgueJS processes the arguments - * object. This allows for simple handling of optional arguments in the - * middle of the argument list, and also provides type checking. */ - var args = arguejs({argument: null, metadata: [Metadata, new Metadata()], - options: [Object], callback: Function}, arguments); - var emitter = new EventEmitter(); - var call = getCall(this.$channel, method, args.options); - metadata = args.metadata.clone(); - emitter.cancel = function cancel() { - call.cancel(); - }; - emitter.getPeer = function getPeer() { - return call.getPeer(); - }; - var client_batch = {}; - var message = serialize(args.argument); - if (args.options) { - message.grpcWriteFlags = args.options.flags; - } - - client_batch[grpc.opType.SEND_INITIAL_METADATA] = - metadata._getCoreRepresentation(); - client_batch[grpc.opType.SEND_MESSAGE] = message; - client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; - client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; - client_batch[grpc.opType.RECV_MESSAGE] = true; - client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; - call.startBatch(client_batch, function(err, response) { - response.status.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); - var status = response.status; - var error; - var deserialized; - emitter.emit('metadata', Metadata._fromCoreRepresentation( - response.metadata)); - if (status.code === grpc.status.OK) { - if (err) { - // Got a batch error, but OK status. Something went wrong - args.callback(err); - return; - } else { - try { - deserialized = deserialize(response.read); - } catch (e) { - /* Change status to indicate bad server response. This will result - * in passing an error to the callback */ - status = { - code: grpc.status.INTERNAL, - details: 'Failed to parse server response' - }; - } - } - } - if (status.code !== grpc.status.OK) { - error = new Error(status.details); - error.code = status.code; - error.metadata = status.metadata; - args.callback(error); - } else { - args.callback(null, deserialized); - } - emitter.emit('status', status); - }); - return emitter; + if (options['grpc.primary_user_agent']) { + options['grpc.primary_user_agent'] += ' '; + } else { + options['grpc.primary_user_agent'] = ''; } - return makeUnaryRequest; -} + options['grpc.primary_user_agent'] += 'grpc-node/' + version; + /* Private fields use $ as a prefix instead of _ because it is an invalid + * prefix of a method name */ + this.$channel = new grpc.Channel(address, credentials, options); +}; + +/** + * @typedef {Error} module:src/client.Client~ServiceError + * @property {number} code The error code, a key of + * [grpc.status]{@link module:src/client.status} + * @property {module:metadata.Metadata} metadata Metadata sent with the status + * by the server, if any + */ + +/** + * @callback module:src/client.Client~requestCallback + * @param {?module:src/client.Client~ServiceError} error The error, if the call + * failed + * @param {*} value The response value, if the call succeeded + */ /** - * Get a function that can make client stream requests to the specified method. + * Make a unary request to the given method, using the given serialize + * and deserialize functions, with the given argument. * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeClientStreamRequest + * @param {module:src/common~serialize} serialize The serialization function for + * inputs + * @param {module:src/common~deserialize} deserialize The deserialization + * function for outputs + * @param {*} argument The argument to the call. Should be serializable with + * serialize + * @param {module:src/metadata.Metadata=} metadata Metadata to add to the call + * @param {module:src/client~CallOptions=} options Options map + * @param {module:src/client.Client~requestCallback} callback The callback to + * for when the response is received + * @return {EventEmitter} An event emitter for stream related events */ -function makeClientStreamRequestFunction(method, serialize, deserialize) { - /** - * Make a client stream request with this method on the given channel with the - * given callback, etc. - * @this {Client} Client object. Must have a channel member. - * @param {Metadata=} metadata Array of metadata key/value pairs to add to the - * call - * @param {Object=} options Options map - * @param {function(?Error, value=)} callback The callback to for when the - * response is received - * @return {EventEmitter} An event emitter for stream related events - */ - function makeClientStreamRequest(metadata, options, callback) { - /* jshint validthis: true */ - /* While the arguments are listed in the function signature, those variables - * are not used directly. Instead, ArgueJS processes the arguments - * object. This allows for simple handling of optional arguments in the - * middle of the argument list, and also provides type checking. */ - var args = arguejs({metadata: [Metadata, new Metadata()], - options: [Object], callback: Function}, arguments); - var call = getCall(this.$channel, method, args.options); - metadata = args.metadata.clone(); - var stream = new ClientWritableStream(call, serialize); - var metadata_batch = {}; - metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = - metadata._getCoreRepresentation(); - metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true; - call.startBatch(metadata_batch, function(err, response) { +Client.prototype.makeUnaryRequest = function(method, serialize, deserialize, + argument, metadata, options, + callback) { + /* While the arguments are listed in the function signature, those variables + * are not used directly. Instead, ArgueJS processes the arguments + * object. This allows for simple handling of optional arguments in the + * middle of the argument list, and also provides type checking. */ + var args = arguejs({method: String, serialize: Function, + deserialize: Function, + argument: null, metadata: [Metadata, new Metadata()], + options: [Object], callback: Function}, arguments); + var call = getCall(this.$channel, method, args.options); + var emitter = new ClientUnaryCall(call); + metadata = args.metadata.clone(); + var client_batch = {}; + var message = serialize(args.argument); + if (args.options) { + message.grpcWriteFlags = args.options.flags; + } + + client_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); + client_batch[grpc.opType.SEND_MESSAGE] = message; + client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + client_batch[grpc.opType.RECV_MESSAGE] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); + var status = response.status; + var error; + var deserialized; + emitter.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); + if (status.code === constants.status.OK) { if (err) { - // The call has stopped for some reason. A non-OK status will arrive - // in the other batch. + // Got a batch error, but OK status. Something went wrong + args.callback(err); return; - } - stream.emit('metadata', Metadata._fromCoreRepresentation( - response.metadata)); - }); - var client_batch = {}; - client_batch[grpc.opType.RECV_MESSAGE] = true; - client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; - call.startBatch(client_batch, function(err, response) { - response.status.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); - var status = response.status; - var error; - var deserialized; - if (status.code === grpc.status.OK) { - if (err) { - // Got a batch error, but OK status. Something went wrong - args.callback(err); - return; - } else { - try { - deserialized = deserialize(response.read); - } catch (e) { - /* Change status to indicate bad server response. This will result - * in passing an error to the callback */ - status = { - code: grpc.status.INTERNAL, - details: 'Failed to parse server response' - }; - } - } - } - if (status.code !== grpc.status.OK) { - error = new Error(response.status.details); - error.code = status.code; - error.metadata = status.metadata; - args.callback(error); } else { - args.callback(null, deserialized); + try { + deserialized = deserialize(response.read); + } catch (e) { + /* Change status to indicate bad server response. This will result + * in passing an error to the callback */ + status = { + code: constants.status.INTERNAL, + details: 'Failed to parse server response' + }; + } } - stream.emit('status', status); - }); - return stream; - } - return makeClientStreamRequest; -} + } + if (status.code !== constants.status.OK) { + error = new Error(status.details); + error.code = status.code; + error.metadata = status.metadata; + args.callback(error); + } else { + args.callback(null, deserialized); + } + emitter.emit('status', status); + }); + return emitter; +}; /** - * Get a function that can make server stream requests to the specified method. + * Make a client stream request to the given method, using the given serialize + * and deserialize functions, with the given argument. * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeServerStreamRequest + * @param {module:src/common~serialize} serialize The serialization function for + * inputs + * @param {module:src/common~deserialize} deserialize The deserialization + * function for outputs + * @param {module:src/metadata.Metadata=} metadata Array of metadata key/value + * pairs to add to the call + * @param {module:src/client~CallOptions=} options Options map + * @param {Client~requestCallback} callback The callback to for when the + * response is received + * @return {module:src/client~ClientWritableStream} An event emitter for stream + * related events */ -function makeServerStreamRequestFunction(method, serialize, deserialize) { - /** - * Make a server stream request with this method on the given channel with the - * given argument, etc. - * @this {SurfaceClient} Client object. Must have a channel member. - * @param {*} argument The argument to the call. Should be serializable with - * serialize - * @param {Metadata=} metadata Array of metadata key/value pairs to add to the - * call - * @param {Object} options Options map - * @return {EventEmitter} An event emitter for stream related events - */ - function makeServerStreamRequest(argument, metadata, options) { - /* jshint validthis: true */ - /* While the arguments are listed in the function signature, those variables - * are not used directly. Instead, ArgueJS processes the arguments - * object. */ - var args = arguejs({argument: null, metadata: [Metadata, new Metadata()], - options: [Object]}, arguments); - var call = getCall(this.$channel, method, args.options); - metadata = args.metadata.clone(); - var stream = new ClientReadableStream(call, deserialize); - var start_batch = {}; - var message = serialize(args.argument); - if (args.options) { - message.grpcWriteFlags = args.options.flags; +Client.prototype.makeClientStreamRequest = function(method, serialize, + deserialize, metadata, + options, callback) { + /* While the arguments are listed in the function signature, those variables + * are not used directly. Instead, ArgueJS processes the arguments + * object. This allows for simple handling of optional arguments in the + * middle of the argument list, and also provides type checking. */ + var args = arguejs({method:String, serialize: Function, + deserialize: Function, + metadata: [Metadata, new Metadata()], + options: [Object], callback: Function}, arguments); + var call = getCall(this.$channel, method, args.options); + metadata = args.metadata.clone(); + var stream = new ClientWritableStream(call, serialize); + var metadata_batch = {}; + metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); + metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + call.startBatch(metadata_batch, function(err, response) { + if (err) { + // The call has stopped for some reason. A non-OK status will arrive + // in the other batch. + return; } - start_batch[grpc.opType.SEND_INITIAL_METADATA] = - metadata._getCoreRepresentation(); - start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; - start_batch[grpc.opType.SEND_MESSAGE] = message; - start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; - call.startBatch(start_batch, function(err, response) { - if (err) { - // The call has stopped for some reason. A non-OK status will arrive - // in the other batch. - return; - } - stream.emit('metadata', Metadata._fromCoreRepresentation( - response.metadata)); - }); - var status_batch = {}; - status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; - call.startBatch(status_batch, function(err, response) { + stream.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); + }); + var client_batch = {}; + client_batch[grpc.opType.RECV_MESSAGE] = true; + client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(client_batch, function(err, response) { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); + var status = response.status; + var error; + var deserialized; + if (status.code === constants.status.OK) { if (err) { - stream.emit('error', err); + // Got a batch error, but OK status. Something went wrong + args.callback(err); return; + } else { + try { + deserialized = deserialize(response.read); + } catch (e) { + /* Change status to indicate bad server response. This will result + * in passing an error to the callback */ + status = { + code: constants.status.INTERNAL, + details: 'Failed to parse server response' + }; + } } - response.status.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); - stream._receiveStatus(response.status); - }); - return stream; - } - return makeServerStreamRequest; -} + } + if (status.code !== constants.status.OK) { + error = new Error(response.status.details); + error.code = status.code; + error.metadata = status.metadata; + args.callback(error); + } else { + args.callback(null, deserialized); + } + stream.emit('status', status); + }); + return stream; +}; /** - * Get a function that can make bidirectional stream requests to the specified - * method. + * Make a server stream request to the given method, with the given serialize + * and deserialize function, using the given argument * @param {string} method The name of the method to request - * @param {function(*):Buffer} serialize The serialization function for inputs - * @param {function(Buffer)} deserialize The deserialization function for - * outputs - * @return {Function} makeBidiStreamRequest + * @param {module:src/common~serialize} serialize The serialization function for + * inputs + * @param {module:src/common~deserialize} deserialize The deserialization + * function for outputs + * @param {*} argument The argument to the call. Should be serializable with + * serialize + * @param {module:src/metadata.Metadata=} metadata Array of metadata key/value + * pairs to add to the call + * @param {module:src/client~CallOptions=} options Options map + * @return {module:src/client~ClientReadableStream} An event emitter for stream + * related events */ -function makeBidiStreamRequestFunction(method, serialize, deserialize) { - /** - * Make a bidirectional stream request with this method on the given channel. - * @this {SurfaceClient} Client object. Must have a channel member. - * @param {Metadata=} metadata Array of metadata key/value pairs to add to the - * call - * @param {Options} options Options map - * @return {EventEmitter} An event emitter for stream related events - */ - function makeBidiStreamRequest(metadata, options) { - /* jshint validthis: true */ - /* While the arguments are listed in the function signature, those variables - * are not used directly. Instead, ArgueJS processes the arguments - * object. */ - var args = arguejs({metadata: [Metadata, new Metadata()], - options: [Object]}, arguments); - var call = getCall(this.$channel, method, args.options); - metadata = args.metadata.clone(); - var stream = new ClientDuplexStream(call, serialize, deserialize); - var start_batch = {}; - start_batch[grpc.opType.SEND_INITIAL_METADATA] = - metadata._getCoreRepresentation(); - start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; - call.startBatch(start_batch, function(err, response) { - if (err) { - // The call has stopped for some reason. A non-OK status will arrive - // in the other batch. - return; - } - stream.emit('metadata', Metadata._fromCoreRepresentation( - response.metadata)); - }); - var status_batch = {}; - status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; - call.startBatch(status_batch, function(err, response) { - if (err) { - stream.emit('error', err); - return; - } - response.status.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); - stream._receiveStatus(response.status); - }); - return stream; +Client.prototype.makeServerStreamRequest = function(method, serialize, + deserialize, argument, + metadata, options) { + /* While the arguments are listed in the function signature, those variables + * are not used directly. Instead, ArgueJS processes the arguments + * object. */ + var args = arguejs({method:String, serialize: Function, + deserialize: Function, + argument: null, metadata: [Metadata, new Metadata()], + options: [Object]}, arguments); + var call = getCall(this.$channel, method, args.options); + metadata = args.metadata.clone(); + var stream = new ClientReadableStream(call, deserialize); + var start_batch = {}; + var message = serialize(args.argument); + if (args.options) { + message.grpcWriteFlags = args.options.flags; } - return makeBidiStreamRequest; -} + start_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); + start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + start_batch[grpc.opType.SEND_MESSAGE] = message; + start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; + call.startBatch(start_batch, function(err, response) { + if (err) { + // The call has stopped for some reason. A non-OK status will arrive + // in the other batch. + return; + } + stream.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); + }); + var status_batch = {}; + status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(status_batch, function(err, response) { + if (err) { + stream.emit('error', err); + return; + } + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); + stream._receiveStatus(response.status); + }); + return stream; +}; + +/** + * Make a bidirectional stream request with this method on the given channel. + * @param {string} method The name of the method to request + * @param {module:src/common~serialize} serialize The serialization function for + * inputs + * @param {module:src/common~deserialize} deserialize The deserialization + * function for outputs + * @param {module:src/metadata.Metadata=} metadata Array of metadata key/value + * pairs to add to the call + * @param {module:src/client~CallOptions=} options Options map + * @return {module:src/client~ClientDuplexStream} An event emitter for stream + * related events + */ +Client.prototype.makeBidiStreamRequest = function(method, serialize, + deserialize, metadata, + options) { + /* While the arguments are listed in the function signature, those variables + * are not used directly. Instead, ArgueJS processes the arguments + * object. */ + var args = arguejs({method:String, serialize: Function, + deserialize: Function, + metadata: [Metadata, new Metadata()], + options: [Object]}, arguments); + var call = getCall(this.$channel, method, args.options); + metadata = args.metadata.clone(); + var stream = new ClientDuplexStream(call, serialize, deserialize); + var start_batch = {}; + start_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); + start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; + call.startBatch(start_batch, function(err, response) { + if (err) { + // The call has stopped for some reason. A non-OK status will arrive + // in the other batch. + return; + } + stream.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); + }); + var status_batch = {}; + status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; + call.startBatch(status_batch, function(err, response) { + if (err) { + stream.emit('error', err); + return; + } + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); + stream._receiveStatus(response.status); + }); + return stream; +}; + +Client.prototype.close = function() { + this.$channel.close(); +}; + +/** + * Return the underlying channel object for the specified client + * @return {Channel} The channel + */ +Client.prototype.getChannel = function() { + return this.$channel; +}; + +/** + * Wait for the client to be ready. The callback will be called when the + * client has successfully connected to the server, and it will be called + * with an error if the attempt to connect to the server has unrecoverablly + * failed or if the deadline expires. This function will make the channel + * start connecting if it has not already done so. + * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass + * Infinity to wait forever. + * @param {function(Error)} callback The callback to call when done attempting + * to connect. + */ +Client.prototype.waitForReady = function(deadline, callback) { + var self = this; + var checkState = function(err) { + if (err) { + callback(new Error('Failed to connect before the deadline')); + return; + } + var new_state = self.$channel.getConnectivityState(true); + if (new_state === grpc.connectivityState.READY) { + callback(); + } else if (new_state === grpc.connectivityState.FATAL_FAILURE) { + callback(new Error('Failed to connect to server')); + } else { + self.$channel.watchConnectivityState(new_state, deadline, checkState); + } + }; + checkState(); +}; /** * Map with short names for each of the requester maker functions. Used in * makeClientConstructor + * @access private */ -var requester_makers = { - unary: makeUnaryRequestFunction, - server_stream: makeServerStreamRequestFunction, - client_stream: makeClientStreamRequestFunction, - bidi: makeBidiStreamRequestFunction +var requester_funcs = { + unary: Client.prototype.makeUnaryRequest, + server_stream: Client.prototype.makeServerStreamRequest, + client_stream: Client.prototype.makeClientStreamRequest, + bidi: Client.prototype.makeBidiStreamRequest }; function getDefaultValues(metadata, options) { @@ -675,6 +807,7 @@ function getDefaultValues(metadata, options) { /** * Map with wrappers for each type of requester function to make it use the old * argument order with optional arguments after the callback. + * @access private */ var deprecated_request_wrap = { unary: function(makeUnaryRequest) { @@ -700,55 +833,33 @@ var deprecated_request_wrap = { }; /** - * Creates a constructor for a client with the given methods. The methods object - * maps method name to an object with the following keys: - * path: The path on the server for accessing the method. For example, for - * protocol buffers, we use "/service_name/method_name" - * requestStream: bool indicating whether the client sends a stream - * resonseStream: bool indicating whether the server sends a stream - * requestSerialize: function to serialize request objects - * responseDeserialize: function to deserialize response objects - * @param {Object} methods An object mapping method names to method attributes + * Creates a constructor for a client with the given methods, as specified in + * the methods argument. + * @param {module:src/common~ServiceDefinition} methods An object mapping + * method names to method attributes * @param {string} serviceName The fully qualified name of the service - * @param {Object} class_options An options object. Currently only uses the key - * deprecatedArgumentOrder, a boolean that Indicates that the old argument - * order should be used for methods, with optional arguments at the end - * instead of the callback at the end. Defaults to false. This option is - * only a temporary stopgap measure to smooth an API breakage. + * @param {Object} class_options An options object. + * @param {boolean=} [class_options.deprecatedArgumentOrder=false] Indicates + * that the old argument order should be used for methods, with optional + * arguments at the end instead of the callback at the end. This option + * is only a temporary stopgap measure to smooth an API breakage. * It is deprecated, and new code should not use it. - * @return {function(string, Object)} New client constructor + * @return {function(string, Object)} New client constructor, which is a + * subclass of [grpc.Client]{@link module:src/client.Client}, and has the + * same arguments as that constructor. */ exports.makeClientConstructor = function(methods, serviceName, class_options) { if (!class_options) { class_options = {}; } - /** - * Create a client with the given methods - * @constructor - * @param {string} address The address of the server to connect to - * @param {grpc.Credentials} credentials Credentials to use to connect - * to the server - * @param {Object} options Options to pass to the underlying channel - */ - function Client(address, credentials, options) { - if (!options) { - options = {}; - } - /* Append the grpc-node user agent string after the application user agent - * string, and put the combination at the beginning of the user agent string - */ - if (options['grpc.primary_user_agent']) { - options['grpc.primary_user_agent'] += ' '; - } else { - options['grpc.primary_user_agent'] = ''; - } - options['grpc.primary_user_agent'] += 'grpc-node/' + version; - /* Private fields use $ as a prefix instead of _ because it is an invalid - * prefix of a method name */ - this.$channel = new grpc.Channel(address, credentials, options); + + function ServiceClient(address, credentials, options) { + Client.call(this, address, credentials, options); } + util.inherits(ServiceClient, Client); + _.each(methods, function(attrs, name) { var method_type; if (_.startsWith(name, '$')) { @@ -769,20 +880,20 @@ exports.makeClientConstructor = function(methods, serviceName, } var serialize = attrs.requestSerialize; var deserialize = attrs.responseDeserialize; - var method_func = requester_makers[method_type]( - attrs.path, serialize, deserialize); + var method_func = _.partial(requester_funcs[method_type], attrs.path, + serialize, deserialize); if (class_options.deprecatedArgumentOrder) { - Client.prototype[name] = deprecated_request_wrap(method_func); + ServiceClient.prototype[name] = deprecated_request_wrap(method_func); } else { - Client.prototype[name] = method_func; + ServiceClient.prototype[name] = method_func; } // Associate all provided attributes with the method - _.assign(Client.prototype[name], attrs); + _.assign(ServiceClient.prototype[name], attrs); }); - Client.service = methods; + ServiceClient.service = methods; - return Client; + return ServiceClient; }; /** @@ -791,7 +902,7 @@ exports.makeClientConstructor = function(methods, serviceName, * @return {Channel} The channel */ exports.getClientChannel = function(client) { - return client.$channel; + return Client.prototype.getChannel.call(client); }; /** @@ -807,27 +918,13 @@ exports.getClientChannel = function(client) { * to connect. */ exports.waitForClientReady = function(client, deadline, callback) { - var checkState = function(err) { - if (err) { - callback(new Error('Failed to connect before the deadline')); - return; - } - var new_state = client.$channel.getConnectivityState(true); - if (new_state === grpc.connectivityState.READY) { - callback(); - } else if (new_state === grpc.connectivityState.FATAL_FAILURE) { - callback(new Error('Failed to connect to server')); - } else { - client.$channel.watchConnectivityState(new_state, deadline, checkState); - } - }; - checkState(); + Client.prototype.waitForReady.call(client, deadline, callback); }; /** * Map of status code names to status codes */ -exports.status = grpc.status; +exports.status = constants.status; /** * See docs for client.callError diff --git a/src/node/src/common.js b/src/node/src/common.js index 757969dbddb147a162738d6e61977cd6904d7229..4dad60e630f7476fd4e22174c9865425dfc4b2ab 100644 --- a/src/node/src/common.js +++ b/src/node/src/common.js @@ -43,7 +43,8 @@ var _ = require('lodash'); /** * Wrap a function to pass null-like values through without calling it. If no - * function is given, just uses the identity; + * function is given, just uses the identity. + * @private * @param {?function} func The function to wrap * @return {function} The wrapped function */ @@ -90,3 +91,67 @@ exports.defaultGrpcOptions = { enumsAsStrings: true, deprecatedArgumentOrder: false }; + +// JSDoc definitions that are used in multiple other modules + +/** + * The EventEmitter class in the event standard module + * @external EventEmitter + * @see https://nodejs.org/api/events.html#events_class_eventemitter + */ + +/** + * The Readable class in the stream standard module + * @external Readable + * @see https://nodejs.org/api/stream.html#stream_readable_streams + */ + +/** + * The Writable class in the stream standard module + * @external Writable + * @see https://nodejs.org/api/stream.html#stream_writable_streams + */ + +/** + * The Duplex class in the stream standard module + * @external Duplex + * @see https://nodejs.org/api/stream.html#stream_class_stream_duplex + */ + +/** + * A serialization function + * @callback module:src/common~serialize + * @param {*} value The value to serialize + * @return {Buffer} The value serialized as a byte sequence + */ + +/** + * A deserialization function + * @callback module:src/common~deserialize + * @param {Buffer} data The byte sequence to deserialize + * @return {*} The data deserialized as a value + */ + +/** + * An object that completely defines a service method signature. + * @typedef {Object} module:src/common~MethodDefinition + * @property {string} path The method's URL path + * @property {boolean} requestStream Indicates whether the method accepts + * a stream of requests + * @property {boolean} responseStream Indicates whether the method returns + * a stream of responses + * @property {module:src/common~serialize} requestSerialize Serialization + * function for request values + * @property {module:src/common~serialize} responseSerialize Serialization + * function for response values + * @property {module:src/common~deserialize} requestDeserialize Deserialization + * function for request data + * @property {module:src/common~deserialize} responseDeserialize Deserialization + * function for repsonse data + */ + +/** + * An object that completely defines a service. + * @typedef {Object.<string, module:src/common~MethodDefinition>} + * module:src/common~ServiceDefinition + */ diff --git a/src/node/src/constants.js b/src/node/src/constants.js new file mode 100644 index 0000000000000000000000000000000000000000..528dab120e0ee1fb4098a2d60fed1cb3d3e63678 --- /dev/null +++ b/src/node/src/constants.js @@ -0,0 +1,241 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @module + */ + +/* The comments about status codes are copied verbatim (with some formatting + * modifications) from include/grpc/impl/codegen/status.h, for the purpose of + * including them in generated documentation. + */ +/** + * Enum of status codes that gRPC can return + * @readonly + * @enum {number} + */ +exports.status = { + /** Not an error; returned on success */ + OK: 0, + /** The operation was cancelled (typically by the caller). */ + CANCELLED: 1, + /** + * Unknown error. An example of where this error may be returned is + * if a status value received from another address space belongs to + * an error-space that is not known in this address space. Also + * errors raised by APIs that do not return enough error information + * may be converted to this error. + */ + UNKNOWN: 2, + /** + * Client specified an invalid argument. Note that this differs + * from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments + * that are problematic regardless of the state of the system + * (e.g., a malformed file name). + */ + INVALID_ARGUMENT: 3, + /** + * Deadline expired before operation could complete. For operations + * that change the state of the system, this error may be returned + * even if the operation has completed successfully. For example, a + * successful response from a server could have been delayed long + * enough for the deadline to expire. + */ + DEADLINE_EXCEEDED: 4, + /** Some requested entity (e.g., file or directory) was not found. */ + NOT_FOUND: 5, + /** + * Some entity that we attempted to create (e.g., file or directory) + * already exists. + */ + ALREADY_EXISTS: 6, + /** + * The caller does not have permission to execute the specified + * operation. PERMISSION_DENIED must not be used for rejections + * caused by exhausting some resource (use RESOURCE_EXHAUSTED + * instead for those errors). PERMISSION_DENIED must not be + * used if the caller can not be identified (use UNAUTHENTICATED + * instead for those errors). + */ + PERMISSION_DENIED: 7, + /** + * Some resource has been exhausted, perhaps a per-user quota, or + * perhaps the entire file system is out of space. + */ + RESOURCE_EXHAUSTED: 8, + /** + * Operation was rejected because the system is not in a state + * required for the operation's execution. For example, directory + * to be deleted may be non-empty, an rmdir operation is applied to + * a non-directory, etc. + * + * A litmus test that may help a service implementor in deciding + * between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: + * + * - Use UNAVAILABLE if the client can retry just the failing call. + * - Use ABORTED if the client should retry at a higher-level + * (e.g., restarting a read-modify-write sequence). + * - Use FAILED_PRECONDITION if the client should not retry until + * the system state has been explicitly fixed. E.g., if an "rmdir" + * fails because the directory is non-empty, FAILED_PRECONDITION + * should be returned since the client should not retry unless + * they have first fixed up the directory by deleting files from it. + * - Use FAILED_PRECONDITION if the client performs conditional + * REST Get/Update/Delete on a resource and the resource on the + * server does not match the condition. E.g., conflicting + * read-modify-write on the same resource. + */ + FAILED_PRECONDITION: 9, + /** + * The operation was aborted, typically due to a concurrency issue + * like sequencer check failures, transaction aborts, etc. + * + * See litmus test above for deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE. + */ + ABORTED: 10, + /** + * Operation was attempted past the valid range. E.g., seeking or + * reading past end of file. + * + * Unlike INVALID_ARGUMENT, this error indicates a problem that may + * be fixed if the system state changes. For example, a 32-bit file + * system will generate INVALID_ARGUMENT if asked to read at an + * offset that is not in the range [0,2^32-1], but it will generate + * OUT_OF_RANGE if asked to read from an offset past the current + * file size. + * + * There is a fair bit of overlap between FAILED_PRECONDITION and + * OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific + * error) when it applies so that callers who are iterating through + * a space can easily look for an OUT_OF_RANGE error to detect when + * they are done. + */ + OUT_OF_RANGE: 11, + /** Operation is not implemented or not supported/enabled in this service. */ + UNIMPLEMENTED: 12, + /** + * Internal errors. Means some invariants expected by underlying + * system has been broken. If you see one of these errors, + * something is very broken. + */ + INTERNAL: 13, + /** + * The service is currently unavailable. This is a most likely a + * transient condition and may be corrected by retrying with + * a backoff. + * + * See litmus test above for deciding between FAILED_PRECONDITION, + * ABORTED, and UNAVAILABLE. */ + UNAVAILABLE: 14, + /** Unrecoverable data loss or corruption. */ + DATA_LOSS: 15, + /** + * The request does not have valid authentication credentials for the + * operation. + */ + UNAUTHENTICATED: 16 +}; + +/* The comments about propagation bit flags are copied rom + * include/grpc/impl/codegen/propagation_bits.h for the purpose of including + * them in generated documentation. + */ +/** + * Propagation flags: these can be bitwise or-ed to form the propagation option + * for calls. + * + * Users are encouraged to write propagation masks as deltas from the default. + * i.e. write `grpc.propagate.DEFAULTS & ~grpc.propagate.DEADLINE` to disable + * deadline propagation. + * @enum {number} + */ +exports.propagate = { + DEADLINE: 1, + CENSUS_STATS_CONTEXT: 2, + CENSUS_TRACING_CONTEXT: 4, + CANCELLATION: 8, + DEFAULTS: 65535 +}; + +/* Many of the following comments are copied from + * include/grpc/impl/codegen/grpc_types.h + */ +/** + * Call error constants. Call errors almost always indicate bugs in the gRPC + * library, and these error codes are mainly useful for finding those bugs. + * @enum {number} + */ +exports.callError = { + OK: 0, + ERROR: 1, + NOT_ON_SERVER: 2, + NOT_ON_CLIENT: 3, + ALREADY_INVOKED: 5, + NOT_INVOKED: 6, + ALREADY_FINISHED: 7, + TOO_MANY_OPERATIONS: 8, + INVALID_FLAGS: 9, + INVALID_METADATA: 10, + INVALID_MESSAGE: 11, + NOT_SERVER_COMPLETION_QUEUE: 12, + BATCH_TOO_BIG: 13, + PAYLOAD_TYPE_MISMATCH: 14 +}; + +/** + * Write flags: these can be bitwise or-ed to form write options that modify + * how data is written. + * @enum {number} + */ +exports.writeFlags = { + /** + * Hint that the write may be buffered and need not go out on the wire + * immediately. GRPC is free to buffer the message until the next non-buffered + * write, or until writes_done, but it need not buffer completely or at all. + */ + BUFFER_HINT: 1, + /** + * Force compression to be disabled for a particular write + */ + NO_COMPRESS: 2 +}; + +/** + * @enum {number} + */ +exports.logVerbosity = { + DEBUG: 0, + INFO: 1, + ERROR: 2 +}; diff --git a/src/node/src/credentials.js b/src/node/src/credentials.js index 51ff1da01ece7d27d57d8e4fd111276cfe1b5a4c..b1e86bbd09024409b618d29bbdf70a60686c1156 100644 --- a/src/node/src/credentials.js +++ b/src/node/src/credentials.js @@ -71,6 +71,8 @@ var Metadata = require('./metadata.js'); var common = require('./common.js'); +var constants = require('./constants'); + var _ = require('lodash'); /** @@ -97,14 +99,14 @@ exports.createFromMetadataGenerator = function(metadata_generator) { return CallCredentials.createFromPlugin(function(service_url, cb_data, callback) { metadata_generator({service_url: service_url}, function(error, metadata) { - var code = grpc.status.OK; + var code = constants.status.OK; var message = ''; if (error) { message = error.message; if (error.hasOwnProperty('code') && _.isFinite(error.code)) { code = error.code; } else { - code = grpc.status.UNAUTHENTICATED; + code = constants.status.UNAUTHENTICATED; } if (!metadata) { metadata = new Metadata(); @@ -125,7 +127,7 @@ exports.createFromGoogleCredential = function(google_credential) { var service_url = auth_context.service_url; google_credential.getRequestMetadata(service_url, function(err, header) { if (err) { - common.log(grpc.logVerbosity.INFO, 'Auth error:' + err); + common.log(constants.logVerbosity.INFO, 'Auth error:' + err); callback(err); return; } diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index 612361b0eaf52bc82fdcdc48347824b6cddd9464..92cf23998b38b8a4052746a0fd422e69c4276be5 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -35,12 +35,7 @@ * Metadata module * * This module defines the Metadata class, which represents header and trailer - * metadata for gRPC calls. Here is an example of how to use it: - * - * var metadata = new metadata_module.Metadata(); - * metadata.set('key1', 'value1'); - * metadata.add('key1', 'value2'); - * metadata.get('key1') // returns ['value1', 'value2'] + * metadata for gRPC calls. * * @module */ @@ -54,6 +49,12 @@ var grpc = require('./grpc_extension'); /** * Class for storing metadata. Keys are normalized to lowercase ASCII. * @constructor + * @alias module:src/metadata.Metadata + * @example + * var metadata = new metadata_module.Metadata(); + * metadata.set('key1', 'value1'); + * metadata.add('key1', 'value2'); + * metadata.get('key1') // returns ['value1', 'value2'] */ function Metadata() { this._internal_repr = {}; diff --git a/src/node/src/server.js b/src/node/src/server.js index 3450abed08f57fc90c43bb91491e92288ac684e1..08417a74c1e4d8ea178ad483714f9e778784f324 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -57,6 +57,8 @@ var common = require('./common'); var Metadata = require('./metadata'); +var constants = require('./constants'); + var stream = require('stream'); var Readable = stream.Readable; @@ -75,7 +77,7 @@ var EventEmitter = require('events').EventEmitter; function handleError(call, error) { var statusMetadata = new Metadata(); var status = { - code: grpc.status.UNKNOWN, + code: constants.status.UNKNOWN, details: 'Unknown Error' }; if (error.hasOwnProperty('message')) { @@ -115,7 +117,7 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) { var end_batch = {}; var statusMetadata = new Metadata(); var status = { - code: grpc.status.OK, + code: constants.status.OK, details: 'OK' }; if (metadata) { @@ -125,7 +127,7 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) { try { message = serialize(value); } catch (e) { - e.code = grpc.status.INTERNAL; + e.code = constants.status.INTERNAL; handleError(call, e); return; } @@ -151,7 +153,7 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) { function setUpWritable(stream, serialize) { stream.finished = false; stream.status = { - code : grpc.status.OK, + code : constants.status.OK, details : 'OK', metadata : new Metadata() }; @@ -178,7 +180,7 @@ function setUpWritable(stream, serialize) { * @param {Error} err The error object */ function setStatus(err) { - var code = grpc.status.UNKNOWN; + var code = constants.status.UNKNOWN; var details = 'Unknown Error'; var metadata = new Metadata(); if (err.hasOwnProperty('message')) { @@ -284,7 +286,7 @@ function _write(chunk, encoding, callback) { try { message = this.serialize(chunk); } catch (e) { - e.code = grpc.status.INTERNAL; + e.code = constants.status.INTERNAL; callback(e); return; } @@ -353,7 +355,7 @@ function _read(size) { try { deserialized = self.deserialize(data); } catch (e) { - e.code = grpc.status.INTERNAL; + e.code = constants.status.INTERNAL; self.emit('error', e); return; } @@ -489,7 +491,7 @@ function handleUnary(call, handler, metadata) { try { emitter.request = handler.deserialize(result.read); } catch (e) { - e.code = grpc.status.INTERNAL; + e.code = constants.status.INTERNAL; handleError(call, e); return; } @@ -530,7 +532,7 @@ function handleServerStreaming(call, handler, metadata) { try { stream.request = handler.deserialize(result.read); } catch (e) { - e.code = grpc.status.INTERNAL; + e.code = constants.status.INTERNAL; stream.emit('error', e); return; } @@ -636,7 +638,7 @@ function Server(options) { batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { - code: grpc.status.UNIMPLEMENTED, + code: constants.status.UNIMPLEMENTED, details: '', metadata: {} }; @@ -699,7 +701,7 @@ Server.prototype.register = function(name, handler, serialize, deserialize, }; var unimplementedStatusResponse = { - code: grpc.status.UNIMPLEMENTED, + code: constants.status.UNIMPLEMENTED, details: 'The server does not implement this method' }; @@ -759,8 +761,8 @@ Server.prototype.addService = function(service, implementation) { written in the proto file, instead of using JavaScript function naming style */ if (implementation[attrs.originalName] === undefined) { - common.log(grpc.logVerbosity.ERROR, 'Method handler ' + name + ' for ' + - attrs.path + ' expected but not provided'); + common.log(constants.logVerbosity.ERROR, 'Method handler ' + name + + ' for ' + attrs.path + ' expected but not provided'); impl = defaultHandler[method_type]; } else { impl = _.bind(implementation[attrs.originalName], implementation); @@ -790,7 +792,7 @@ Server.prototype.addProtoService = function(service, implementation) { var options; var protobuf_js_5_common = require('./protobuf_js_5_common'); var protobuf_js_6_common = require('./protobuf_js_6_common'); - common.log(grpc.logVerbosity.INFO, + common.log(constants.logVerbosity.INFO, 'Server#addProtoService is deprecated. Use addService instead'); if (protobuf_js_5_common.isProbablyProtobufJs5(service)) { options = _.defaults(service.grpc_options, common.defaultGrpcOptions); diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js index eb268603ead8a899fe10334292c13aff6e98eca6..f25268e8e6dcc8c7f6bc0cf175c6d0e49c26da72 100644 --- a/src/node/test/call_test.js +++ b/src/node/test/call_test.js @@ -35,6 +35,7 @@ var assert = require('assert'); var grpc = require('../src/grpc_extension'); +var constants = require('../src/constants'); /** * Helper function to return an absolute deadline given a relative timeout in @@ -120,7 +121,8 @@ describe('call', function() { var batch = {}; batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(batch, function(err, response) { - assert.strictEqual(response.status.code, grpc.status.DEADLINE_EXCEEDED); + assert.strictEqual(response.status.code, + constants.status.DEADLINE_EXCEEDED); done(); }); }); diff --git a/src/node/test/constant_test.js b/src/node/test/constant_test.js deleted file mode 100644 index 414b1ac9c019e5fa7c7604c478dddd21acc5bda8..0000000000000000000000000000000000000000 --- a/src/node/test/constant_test.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -'use strict'; - -var assert = require('assert'); -var grpc = require('../src/grpc_extension'); - -/** - * List of all status names - * @const - * @type {Array.<string>} - */ -var statusNames = [ - 'OK', - 'CANCELLED', - 'UNKNOWN', - 'INVALID_ARGUMENT', - 'DEADLINE_EXCEEDED', - 'NOT_FOUND', - 'ALREADY_EXISTS', - 'PERMISSION_DENIED', - 'UNAUTHENTICATED', - 'RESOURCE_EXHAUSTED', - 'FAILED_PRECONDITION', - 'ABORTED', - 'OUT_OF_RANGE', - 'UNIMPLEMENTED', - 'INTERNAL', - 'UNAVAILABLE', - 'DATA_LOSS' -]; - -/** - * List of all call error names - * @const - * @type {Array.<string>} - */ -var callErrorNames = [ - 'OK', - 'ERROR', - 'NOT_ON_SERVER', - 'NOT_ON_CLIENT', - 'ALREADY_INVOKED', - 'NOT_INVOKED', - 'ALREADY_FINISHED', - 'TOO_MANY_OPERATIONS', - 'INVALID_FLAGS' -]; - -/** - * List of all propagate flag names - * @const - * @type {Array.<string>} - */ -var propagateFlagNames = [ - 'DEADLINE', - 'CENSUS_STATS_CONTEXT', - 'CENSUS_TRACING_CONTEXT', - 'CANCELLATION', - 'DEFAULTS' -]; -/* - * List of all connectivity state names - * @const - * @type {Array.<string>} - */ -var connectivityStateNames = [ - 'IDLE', - 'CONNECTING', - 'READY', - 'TRANSIENT_FAILURE', - 'FATAL_FAILURE' -]; - -describe('constants', function() { - it('should have all of the status constants', function() { - for (var i = 0; i < statusNames.length; i++) { - assert(grpc.status.hasOwnProperty(statusNames[i]), - 'status missing: ' + statusNames[i]); - } - }); - it('should have all of the call errors', function() { - for (var i = 0; i < callErrorNames.length; i++) { - assert(grpc.callError.hasOwnProperty(callErrorNames[i]), - 'call error missing: ' + callErrorNames[i]); - } - }); - it('should have all of the propagate flags', function() { - for (var i = 0; i < propagateFlagNames.length; i++) { - assert(grpc.propagate.hasOwnProperty(propagateFlagNames[i]), - 'call error missing: ' + propagateFlagNames[i]); - } - }); - it('should have all of the connectivity states', function() { - for (var i = 0; i < connectivityStateNames.length; i++) { - assert(grpc.connectivityState.hasOwnProperty(connectivityStateNames[i]), - 'connectivity status missing: ' + connectivityStateNames[i]); - } - }); -}); diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index f127a41de9ffc38ae43ba439f2862b40bc0e4b9f..af455e2716d9a93e47739e38031c70d3d3c66244 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -35,6 +35,7 @@ var assert = require('assert'); var grpc = require('../src/grpc_extension'); +var constants = require('../src/constants'); /** * This is used for testing functions with multiple asynchronous calls that @@ -90,7 +91,7 @@ describe('end-to-end', function() { client_close: true, metadata: {}, status: { - code: grpc.status.OK, + code: constants.status.OK, details: status_text, metadata: {} } @@ -107,7 +108,7 @@ describe('end-to-end', function() { server_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, - code: grpc.status.OK, + code: constants.status.OK, details: status_text }; server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; @@ -141,7 +142,7 @@ describe('end-to-end', function() { send_metadata: true, client_close: true, metadata: {server_key: ['server_value']}, - status: {code: grpc.status.OK, + status: {code: constants.status.OK, details: status_text, metadata: {}} }); @@ -161,7 +162,7 @@ describe('end-to-end', function() { }; server_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, - code: grpc.status.OK, + code: constants.status.OK, details: status_text }; server_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; @@ -198,7 +199,7 @@ describe('end-to-end', function() { assert.deepEqual(response.metadata, {}); assert(response.send_message); assert.strictEqual(response.read.toString(), reply_text); - assert.deepEqual(response.status, {code: grpc.status.OK, + assert.deepEqual(response.status, {code: constants.status.OK, details: status_text, metadata: {}}); done(); @@ -220,7 +221,7 @@ describe('end-to-end', function() { response_batch[grpc.opType.SEND_MESSAGE] = new Buffer(reply_text); response_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, - code: grpc.status.OK, + code: constants.status.OK, details: status_text }; response_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; @@ -260,7 +261,7 @@ describe('end-to-end', function() { send_message: true, client_close: true, status: { - code: grpc.status.OK, + code: constants.status.OK, details: status_text, metadata: {} } @@ -290,7 +291,7 @@ describe('end-to-end', function() { end_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true; end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { metadata: {}, - code: grpc.status.OK, + code: constants.status.OK, details: status_text }; server_call.startBatch(end_batch, function(err, response) { diff --git a/src/php/composer.json b/src/php/composer.json index 24c17c3b572dacf45772a44005d11a71a09cda1e..a4fba7e4f6a888a963e4ccbc689c02057022fc85 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -5,7 +5,7 @@ "version": "1.4.0", "require": { "php": ">=5.5.0", - "google/protobuf": "^v3.1.0" + "google/protobuf": "^v3.3.0" }, "require-dev": { "google/auth": "v0.9" diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index 4f072809c4741a35599f12d90a069f2866f26ad9..f4ccb1ab94c6a529b694062fdcd0bc100552a06f 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -284,9 +284,9 @@ class BuildExt(build_ext.build_ext): stderr=subprocess.PIPE) make_out, make_err = make_process.communicate() if make_out and make_process.returncode != 0: - sys.stdout.write(make_out + '\n') + sys.stdout.write(str(make_out) + '\n') if make_err: - sys.stderr.write(make_err + '\n') + sys.stderr.write(str(make_err) + '\n') if make_process.returncode != 0: raise Exception("make command failed!") diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index 64c51ee6a0e6b5ddce64721d01958b2ad1baef26..5426b47c76185f75774e6006ae5125b1c08fd708 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -66,7 +66,8 @@ class Future(six.with_metaclass(abc.ABCMeta)): Returns False under all other circumstances, for example: 1. computation has begun and could not be canceled. 2. computation has finished - 3. computation is scheduled for execution and it is impossible to determine its state without blocking. + 3. computation is scheduled for execution and it is impossible to + determine its state without blocking. """ raise NotImplementedError() @@ -123,8 +124,8 @@ class Future(six.with_metaclass(abc.ABCMeta)): Args: timeout: The length of time in seconds to wait for the computation to - finish or be cancelled. If None, the call will block until the computations's - termination. + finish or be cancelled. If None, the call will block until the + computations's termination. Returns: The return value of the computation. @@ -146,8 +147,8 @@ class Future(six.with_metaclass(abc.ABCMeta)): Args: timeout: The length of time in seconds to wait for the computation to - terminate or be cancelled. If None, the call will block until the computations's - termination. + terminate or be cancelled. If None, the call will block until the + computations's termination. Returns: The exception raised by the computation, or None if the computation did @@ -363,9 +364,9 @@ class ChannelCredentials(object): """An encapsulation of the data required to create a secure Channel. This class has no supported interface - it exists to define the type of its - instances and its instances exist to be passed to other functions. For example, - ssl_channel_credentials returns an instance, and secure_channel consumes an - instance of this class. + instances and its instances exist to be passed to other functions. For + example, ssl_channel_credentials returns an instance, and secure_channel + consumes an instance of this class. """ def __init__(self, credentials): @@ -373,7 +374,8 @@ class ChannelCredentials(object): class CallCredentials(object): - """An encapsulation of the data required to assert an identity over a channel. + """An encapsulation of the data required to assert an identity over a + channel. A CallCredentials may be composed with ChannelCredentials to always assert identity for every call over that Channel. @@ -399,7 +401,8 @@ class AuthMetadataPluginCallback(six.with_metaclass(abc.ABCMeta)): """Callback object received by a metadata plugin.""" def __call__(self, metadata, error): - """Inform the gRPC runtime of the metadata to construct a CallCredentials. + """Inform the gRPC runtime of the metadata to construct a + CallCredentials. Args: metadata: The :term:`metadata` used to construct the CallCredentials. @@ -773,6 +776,42 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() + @abc.abstractmethod + def peer_identities(self): + """Gets one or more peer identity(s). + + Equivalent to + servicer_context.auth_context().get( + servicer_context.peer_identity_key()) + + Returns: + An iterable of the identities, or None if the call is not authenticated. + Each identity is returned as a raw bytes type. + """ + raise NotImplementedError() + + @abc.abstractmethod + def peer_identity_key(self): + """The auth property used to identify the peer. + + For example, "x509_common_name" or "x509_subject_alternative_name" are + used to identify an SSL peer. + + Returns: + The auth property (string) that indicates the + peer identity, or None if the call is not authenticated. + """ + raise NotImplementedError() + + @abc.abstractmethod + def auth_context(self): + """Gets the auth context for the call. + + Returns: + A map of strings to an iterable of bytes for each auth property. + """ + raise NotImplementedError() + @abc.abstractmethod def send_initial_metadata(self, initial_metadata): """Sends the initial metadata value to the client. @@ -879,8 +918,8 @@ class GenericRpcHandler(six.with_metaclass(abc.ABCMeta)): handler_call_details: A HandlerCallDetails describing the RPC. Returns: - An RpcMethodHandler with which the RPC may be serviced if the implementation - chooses to service this RPC, or None otherwise. + An RpcMethodHandler with which the RPC may be serviced if the + implementation chooses to service this RPC, or None otherwise. """ raise NotImplementedError() diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index 1db2056d476a70394eb5cb49f46307dc5d526158..e71d3e7dc1c1658f1d02ee8613f7f4de75b6f47f 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -486,6 +486,35 @@ cdef extern from "grpc/grpc_security.h": grpc_call_credentials *grpc_metadata_credentials_create_from_plugin( grpc_metadata_credentials_plugin plugin, void *reserved) nogil + ctypedef struct grpc_auth_property_iterator: + pass + + ctypedef struct grpc_auth_property: + char *name + char *value + size_t value_length + + grpc_auth_property *grpc_auth_property_iterator_next( + grpc_auth_property_iterator *it) + + grpc_auth_property_iterator grpc_auth_context_property_iterator( + const grpc_auth_context *ctx) + + grpc_auth_property_iterator grpc_auth_context_peer_identity( + const grpc_auth_context *ctx) + + char *grpc_auth_context_peer_identity_property_name( + const grpc_auth_context *ctx) + + grpc_auth_property_iterator grpc_auth_context_find_properties_by_name( + const grpc_auth_context *ctx, const char *name) + + grpc_auth_context_peer_is_authenticated( + const grpc_auth_context *ctx) + + grpc_auth_context *grpc_call_auth_context(grpc_call *call) + + void grpc_auth_context_release(grpc_auth_context *context) cdef extern from "grpc/compression.h": diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi index 357b0330d5ce7c9295f74d298dbed33c8de79c4d..a21eac79951004f3946e8afae17a9d2e18568dc7 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/security.pyx.pxi @@ -44,3 +44,61 @@ cdef grpc_ssl_roots_override_result ssl_roots_override_callback( pem_root_certs[0][len(temporary_pem_root_certs)] = '\0' return GRPC_SSL_ROOTS_OVERRIDE_OK + + +def peer_identities(Call call): + cdef grpc_auth_context* auth_context + cdef grpc_auth_property_iterator properties + cdef grpc_auth_property* property + + auth_context = grpc_call_auth_context(call.c_call) + if auth_context == NULL: + return None + properties = grpc_auth_context_peer_identity(auth_context) + identities = [] + while True: + property = grpc_auth_property_iterator_next(&properties) + if property == NULL: + break + if property.value != NULL: + identities.append(<bytes>(property.value)) + grpc_auth_context_release(auth_context) + return identities if identities else None + +def peer_identity_key(Call call): + cdef grpc_auth_context* auth_context + cdef char* c_key + auth_context = grpc_call_auth_context(call.c_call) + if auth_context == NULL: + return None + c_key = grpc_auth_context_peer_identity_property_name(auth_context) + if c_key == NULL: + key = None + else: + key = <bytes> grpc_auth_context_peer_identity_property_name(auth_context) + grpc_auth_context_release(auth_context) + return key + +def auth_context(Call call): + cdef grpc_auth_context* auth_context + cdef grpc_auth_property_iterator properties + cdef grpc_auth_property* property + + auth_context = grpc_call_auth_context(call.c_call) + if auth_context == NULL: + return {} + properties = grpc_auth_context_property_iterator(auth_context) + py_auth_context = {} + while True: + property = grpc_auth_property_iterator_next(&properties) + if property == NULL: + break + if property.name != NULL and property.value != NULL: + key = <bytes> property.name + if key in py_auth_context: + py_auth_context[key].append(<bytes>(property.value)) + else: + py_auth_context[key] = [<bytes> property.value] + grpc_auth_context_release(auth_context) + return py_auth_context + diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index f29c44a4cfd3e35b9dfbc01b08f2cfe882423172..860085f0c7ee0ebde58cafa1768fb8912e262872 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -31,6 +31,7 @@ import collections import enum import logging +import six import threading import time @@ -255,6 +256,20 @@ class _Context(grpc.ServicerContext): def peer(self): return _common.decode(self._rpc_event.operation_call.peer()) + def peer_identities(self): + return cygrpc.peer_identities(self._rpc_event.operation_call) + + def peer_identity_key(self): + id_key = cygrpc.peer_identity_key(self._rpc_event.operation_call) + return id_key if id_key is None else _common.decode(id_key) + + def auth_context(self): + return { + _common.decode(key): value + for key, value in six.iteritems( + cygrpc.auth_context(self._rpc_event.operation_call)) + } + def send_initial_metadata(self, initial_metadata): with self._state.condition: if self._state.client is _CANCELLED: diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 6c3b47a214e1855c8ad9c960f051137339d9324e..502e9462265885f6954b9f940d83cd9f9814aaec 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -86,7 +86,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/channel/handshaker_registry.c', 'src/core/lib/compression/compression.c', 'src/core/lib/compression/message_compress.c', - 'src/core/lib/debug/trace.c', 'src/core/lib/http/format_request.c', 'src/core/lib/http/httpcli.c', 'src/core/lib/http/parser.c', @@ -97,7 +96,11 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/endpoint_pair_uv.c', 'src/core/lib/iomgr/endpoint_pair_windows.c', 'src/core/lib/iomgr/error.c', - 'src/core/lib/iomgr/ev_epoll_linux.c', + 'src/core/lib/iomgr/ev_epoll1_linux.c', + 'src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c', + 'src/core/lib/iomgr/ev_epoll_thread_pool_linux.c', + 'src/core/lib/iomgr/ev_epollex_linux.c', + 'src/core/lib/iomgr/ev_epollsig_linux.c', 'src/core/lib/iomgr/ev_poll_posix.c', 'src/core/lib/iomgr/ev_posix.c', 'src/core/lib/iomgr/exec_ctx.c', @@ -107,6 +110,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/iomgr_posix.c', 'src/core/lib/iomgr/iomgr_uv.c', 'src/core/lib/iomgr/iomgr_windows.c', + 'src/core/lib/iomgr/is_epollexclusive_available.c', 'src/core/lib/iomgr/load_file.c', 'src/core/lib/iomgr/lockfree_event.c', 'src/core/lib/iomgr/network_status_tracker.c', @@ -143,6 +147,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/time_averaged_stats.c', 'src/core/lib/iomgr/timer_generic.c', 'src/core/lib/iomgr/timer_heap.c', + 'src/core/lib/iomgr/timer_manager.c', 'src/core/lib/iomgr/timer_uv.c', 'src/core/lib/iomgr/udp_server.c', 'src/core/lib/iomgr/unix_sockets_posix.c', @@ -197,6 +202,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/transport/timeout_encoding.c', 'src/core/lib/transport/transport.c', 'src/core/lib/transport/transport_op_string.c', + 'src/core/lib/debug/trace.c', 'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c', 'src/core/ext/transport/chttp2/transport/bin_decoder.c', 'src/core/ext/transport/chttp2/transport/bin_encoder.c', diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index 1806d311b47658b9a6a3496f78741b00e7c08d6b..f1c09de2eb1f0d6ca474a256e603bec91c922ce6 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -46,7 +46,7 @@ PACKAGE_DIRECTORIES = { SETUP_REQUIRES = ( 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),) -INSTALL_REQUIRES = ('protobuf>=3.2.0', +INSTALL_REQUIRES = ('protobuf>=3.3.0', 'grpcio>={version}'.format(version=grpc_version.VERSION),) COMMAND_CLASS = { diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py index e6cf54745e2d945f492bad31c25f55e215577029..cb49c3d57e7b608542e36f6a4f5950dfae69db78 100644 --- a/src/python/grpcio_reflection/setup.py +++ b/src/python/grpcio_reflection/setup.py @@ -47,7 +47,7 @@ PACKAGE_DIRECTORIES = { SETUP_REQUIRES = ( 'grpcio-tools>={version}'.format(version=grpc_version.VERSION),) -INSTALL_REQUIRES = ('protobuf>=3.2.0', +INSTALL_REQUIRES = ('protobuf>=3.3.0', 'grpcio>={version}'.format(version=grpc_version.VERSION),) COMMAND_CLASS = { diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py index b9f0264dae3a29eb025a6bc4ba301b0156e3ef8c..7ee5336a7d6cd07182d2bb8fffecaa3417c72c02 100644 --- a/src/python/grpcio_tests/setup.py +++ b/src/python/grpcio_tests/setup.py @@ -56,7 +56,7 @@ INSTALL_REQUIRES = ( 'grpcio>={version}'.format(version=grpc_version.VERSION), 'grpcio-tools>={version}'.format(version=grpc_version.VERSION), 'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION), - 'oauth2client>=1.4.7', 'protobuf>=3.2.0', 'six>=1.10',) + 'oauth2client>=1.4.7', 'protobuf>=3.3.0', 'six>=1.10',) COMMAND_CLASS = { # Run `preprocess` *before* doing any packaging! diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json index f750b0510220ee7078896ba7f88503617c1cdbb5..9f7587faa667e4ab460dd1bb27e8709a778f34ea 100644 --- a/src/python/grpcio_tests/tests/tests.json +++ b/src/python/grpcio_tests/tests/tests.json @@ -12,6 +12,7 @@ "unit._api_test.AllTest", "unit._api_test.ChannelConnectivityTest", "unit._api_test.ChannelTest", + "unit._auth_context_test.AuthContextTest", "unit._auth_test.AccessTokenCallCredentialsTest", "unit._auth_test.GoogleCallCredentialsTest", "unit._channel_args_test.ChannelArgsTest", diff --git a/src/python/grpcio_tests/tests/unit/_auth_context_test.py b/src/python/grpcio_tests/tests/unit/_auth_context_test.py new file mode 100644 index 0000000000000000000000000000000000000000..fce6ac967dbd57890a5dbb07c22d6738b443aa22 --- /dev/null +++ b/src/python/grpcio_tests/tests/unit/_auth_context_test.py @@ -0,0 +1,154 @@ +# Copyright 2017, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +"""Tests exposure of SSL auth context""" + +import pickle +import unittest + +import grpc +from grpc import _channel +from grpc.framework.foundation import logging_pool +import six + +from tests.unit import test_common +from tests.unit.framework.common import test_constants +from tests.unit import resources + +_REQUEST = b'\x00\x00\x00' +_RESPONSE = b'\x00\x00\x00' + +_UNARY_UNARY = '/test/UnaryUnary' + +_SERVER_HOST_OVERRIDE = 'foo.test.google.fr' +_CLIENT_IDS = (b'*.test.google.fr', b'waterzooi.test.google.be', + b'*.test.youtube.com', b'192.168.1.3',) +_ID = 'id' +_ID_KEY = 'id_key' +_AUTH_CTX = 'auth_ctx' + +_PRIVATE_KEY = resources.private_key() +_CERTIFICATE_CHAIN = resources.certificate_chain() +_TEST_ROOT_CERTIFICATES = resources.test_root_certificates() +_SERVER_CERTS = ((_PRIVATE_KEY, _CERTIFICATE_CHAIN),) +_PROPERTY_OPTIONS = (('grpc.ssl_target_name_override', _SERVER_HOST_OVERRIDE,),) + + +def handle_unary_unary(request, servicer_context): + return pickle.dumps({ + _ID: servicer_context.peer_identities(), + _ID_KEY: servicer_context.peer_identity_key(), + _AUTH_CTX: servicer_context.auth_context() + }) + + +class AuthContextTest(unittest.TestCase): + + def testInsecure(self): + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + handler = grpc.method_handlers_generic_handler('test', { + 'UnaryUnary': + grpc.unary_unary_rpc_method_handler(handle_unary_unary) + }) + server = grpc.server(server_pool, (handler,)) + port = server.add_insecure_port('[::]:0') + server.start() + + channel = grpc.insecure_channel('localhost:%d' % port) + response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) + server.stop(None) + + auth_data = pickle.loads(response) + self.assertIsNone(auth_data[_ID]) + self.assertIsNone(auth_data[_ID_KEY]) + self.assertDictEqual({}, auth_data[_AUTH_CTX]) + + def testSecureNoCert(self): + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + handler = grpc.method_handlers_generic_handler('test', { + 'UnaryUnary': + grpc.unary_unary_rpc_method_handler(handle_unary_unary) + }) + server = grpc.server(server_pool, (handler,)) + server_cred = grpc.ssl_server_credentials(_SERVER_CERTS) + port = server.add_secure_port('[::]:0', server_cred) + server.start() + + channel_creds = grpc.ssl_channel_credentials( + root_certificates=_TEST_ROOT_CERTIFICATES) + channel = grpc.secure_channel( + 'localhost:{}'.format(port), + channel_creds, + options=_PROPERTY_OPTIONS) + response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) + server.stop(None) + + auth_data = pickle.loads(response) + self.assertIsNone(auth_data[_ID]) + self.assertIsNone(auth_data[_ID_KEY]) + self.assertDictEqual({ + 'transport_security_type': [b'ssl'] + }, auth_data[_AUTH_CTX]) + + def testSecureClientCert(self): + server_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY) + handler = grpc.method_handlers_generic_handler('test', { + 'UnaryUnary': + grpc.unary_unary_rpc_method_handler(handle_unary_unary) + }) + server = grpc.server(server_pool, (handler,)) + server_cred = grpc.ssl_server_credentials( + _SERVER_CERTS, + root_certificates=_TEST_ROOT_CERTIFICATES, + require_client_auth=True) + port = server.add_secure_port('[::]:0', server_cred) + server.start() + + channel_creds = grpc.ssl_channel_credentials( + root_certificates=_TEST_ROOT_CERTIFICATES, + private_key=_PRIVATE_KEY, + certificate_chain=_CERTIFICATE_CHAIN) + channel = grpc.secure_channel( + 'localhost:{}'.format(port), + channel_creds, + options=_PROPERTY_OPTIONS) + + response = channel.unary_unary(_UNARY_UNARY)(_REQUEST) + server.stop(None) + + auth_data = pickle.loads(response) + auth_ctx = auth_data[_AUTH_CTX] + six.assertCountEqual(self, _CLIENT_IDS, auth_data[_ID]) + self.assertEqual('x509_subject_alternative_name', auth_data[_ID_KEY]) + self.assertSequenceEqual([b'ssl'], auth_ctx['transport_security_type']) + self.assertSequenceEqual([b'*.test.google.com'], + auth_ctx['x509_common_name']) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/templates/Makefile.template b/templates/Makefile.template index 5ce606f8280145c3c1832777d628d78af89e4504..a9dd171b8410048475abb8fe3fdd92c499710fb3 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -206,10 +206,6 @@ TMPOUT = `mktemp /tmp/test-out-XXXXXX` endif - # Detect if we can use C++11 - CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc - HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false) - %for warning in CHECK_WARNINGS: ${warning_var('CHECK_%s_WORKS_CMD', warning)} = $(CC) -std=c99 -Werror -W${warning} -o $(TMPOUT) -c test/build/${warning}.c ${warning_var('HAS_WORKING_%s', warning)} = $(shell $(${warning_var('CHECK_%s_WORKS_CMD', warning)}) 2> /dev/null && echo true || echo false) @@ -230,11 +226,7 @@ HOST_LDXX ?= $(LDXX) CFLAGS += -std=c99 -Wsign-conversion -Wconversion ${' '.join(warning_var('$(W_%s)', warning) for warning in PREFERRED_WARNINGS)} - ifeq ($(HAS_CXX11),true) CXXFLAGS += -std=c++11 - else - CXXFLAGS += -std=c++0x - endif % for arg in ['CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS', 'DEFINES']: % if defaults.get('global', []).get(arg, None) is not None: ${arg} += ${defaults.get('global').get(arg)} diff --git a/templates/composer.json.template b/templates/composer.json.template index 94f0c236a9606d43dc5a5b2d02a762fb99215055..2d4cb119195dbb4555cef7d35a67fcf086270739 100644 --- a/templates/composer.json.template +++ b/templates/composer.json.template @@ -9,7 +9,7 @@ "license": "BSD-3-Clause", "require": { "php": ">=5.5.0", - "google/protobuf": "^v3.1.0" + "google/protobuf": "^v3.3.0" }, "require-dev": { "google/auth": "v0.9" diff --git a/templates/src/csharp/Grpc.Core/Version.csproj.include.template b/templates/src/csharp/Grpc.Core/Version.csproj.include.template index 30b8d26375bfc369a238ecd84b70ded67dd1f0f9..5bc66e911b2c32fca604a6a947695df93d7a9d7b 100755 --- a/templates/src/csharp/Grpc.Core/Version.csproj.include.template +++ b/templates/src/csharp/Grpc.Core/Version.csproj.include.template @@ -4,6 +4,6 @@ <Project> <PropertyGroup> <GrpcCsharpVersion>${settings.csharp_version}</GrpcCsharpVersion> - <GoogleProtobufVersion>3.2.0</GoogleProtobufVersion> + <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion> </PropertyGroup> </Project> diff --git a/templates/src/php/composer.json.template b/templates/src/php/composer.json.template index 1887ee3c822afd08725295d1749b9d5db2257f15..36932cf8f61189404d0b63acd92d6443ce8b8f0e 100644 --- a/templates/src/php/composer.json.template +++ b/templates/src/php/composer.json.template @@ -7,7 +7,7 @@ "version": "${settings.php_version.php_composer()}", "require": { "php": ">=5.5.0", - "google/protobuf": "^v3.1.0" + "google/protobuf": "^v3.3.0" }, "require-dev": { "google/auth": "v0.9" diff --git a/templates/tools/dockerfile/gcp_api_libraries.include b/templates/tools/dockerfile/gcp_api_libraries.include index 669b0f887c820a41afe4377669aa39516bcec913..adecb92c150e3cf1427155c1f8ca7ed91b6411d5 100644 --- a/templates/tools/dockerfile/gcp_api_libraries.include +++ b/templates/tools/dockerfile/gcp_api_libraries.include @@ -1,4 +1,3 @@ # Google Cloud platform API libraries RUN apt-get update && apt-get install -y python-pip && apt-get clean RUN pip install --upgrade google-api-python-client - diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile.template similarity index 94% rename from templates/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile.template rename to templates/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile.template index ad8ad71b5fab2ea955b43efcc4fccd0da08b3b1e..b4e618daeb73b7e37f222ac9c46d821d86b95550 100644 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile.template @@ -1,6 +1,6 @@ %YAML 1.2 --- | - # Copyright 2016, Google Inc. + # Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,10 +29,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - FROM golang:latest + FROM golang:1.7 - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../python_deps.include"/> <%include file="../../go_path.include"/> + <%include file="../../python_deps.include"/> # Define the default command. CMD ["bash"] + diff --git a/templates/tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile.template similarity index 88% rename from templates/tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh.template rename to templates/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile.template index b885101748410804cef50dfc6aa7a7d2e5bfff64..437e8261b3a1b3840870534aa23879dec225f3c8 100644 --- a/templates/tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile.template @@ -1,7 +1,6 @@ %YAML 1.2 --- | - #!/bin/bash - # Copyright 2016, Google Inc. + # Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -29,9 +28,11 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - set -ex - - cd /var/local/git/grpc - cp /${openssl_fallback.tarball} third_party - ./tools/openssl/use_openssl.sh + + FROM golang:1.8 + + <%include file="../../go_path.include"/> + <%include file="../../python_deps.include"/> + # Define the default command. + CMD ["bash"] + diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile.template deleted file mode 100644 index 5d805bb4b22d1cf69fc38773f4371747f90124aa..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile.template +++ /dev/null @@ -1,42 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2015, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../ccache_setup.include"/> - <%include file="../../cxx_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../csharp_deps.include"/> - # Define the default command. - CMD ["bash"] - diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile.template deleted file mode 100644 index 18f06b770c3031a4c569f6035a66b6efa2042baf..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile.template +++ /dev/null @@ -1,41 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2015-2016, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../ccache_setup.include"/> - <%include file="../../cxx_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../clang_update.include"/> - # Define the default command. - CMD ["bash"] diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile.template deleted file mode 100644 index 2bb2f9ba1e6f5e90b1913a6759c1bfb70b76c6de..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile.template +++ /dev/null @@ -1,41 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2016, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../ccache_setup.include"/> - <%include file="../../cxx_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../java_deps.include"/> - # Define the default command. - CMD ["bash"] diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile.template deleted file mode 100644 index d70b751b141ec304786dfb4058e3bce62606561d..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile.template +++ /dev/null @@ -1,40 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2016, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../node_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../run_tests_addons.include"/> - # Define the default command. - CMD ["bash"] diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_php/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_php/Dockerfile.template deleted file mode 100644 index 49ba60168da13ff905f6baf3590579cd468e29f7..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_php/Dockerfile.template +++ /dev/null @@ -1,46 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2015, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../ruby_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../php_deps.include"/> - <%include file="../../run_tests_addons.include"/> - # Install composer - RUN curl -sS https://getcomposer.org/installer | php - RUN mv composer.phar /usr/local/bin/composer - - # Define the default command. - CMD ["bash"] - diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile.template deleted file mode 100644 index 27e9eeec5a838cbdee017b258a33ec42f14985e4..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile.template +++ /dev/null @@ -1,45 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2016, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../ccache_setup.include"/> - <%include file="../../cxx_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../python_deps.include"/> - - RUN pip install coverage - RUN pip install oauth2client - - # Define the default command. - CMD ["bash"] - diff --git a/templates/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile.template b/templates/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile.template deleted file mode 100644 index 18199771d7ec0ff281545f7fc4f6940db58cf9ac..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile.template +++ /dev/null @@ -1,42 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2015, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:jessie - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../ccache_setup.include"/> - <%include file="../../cxx_deps.include"/> - <%include file="../../gcp_api_libraries.include"/> - <%include file="../../ruby_deps.include"/> - # Define the default command. - CMD ["bash"] - diff --git a/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template index 092f04dac6c991f902c80847b3064bce65bfcf97..f869cf9106a56a9b46a0a0f11a41f7bdb69147c8 100644 --- a/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/csharp_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../csharp_deps.include"/> <%include file="../../csharp_dotnetcli_deps.include"/> diff --git a/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template index 35b0e177fb6a44efc12045c8ac1bba4b10f6717a..a42215d257056eb733b80801a27b5fe09db8e954 100644 --- a/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../cxx_deps.include"/> <%include file="../../clang_update.include"/> diff --git a/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template b/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template index 643b5cb65ba3c3a2a5c3b9b2003982f39fd64f92..9df81583828230390bac0cc0905037c07924a1d7 100644 --- a/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template @@ -32,6 +32,7 @@ FROM 32bit/debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../cxx_deps.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template index 8a95cad6492baed88108e3ce4663d66baf5690ea..98854ff1c4f84eab48904bfccb3049f44f509ff5 100644 --- a/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM ubuntu:14.04 <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../cxx_deps.include"/> <%include file="../../run_tests_addons_nocache.include"/> diff --git a/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template index 42ad6c130da5f69006d46a6f1f5f4fda35c34c20..3ad65e9eeee73cd7288a08190b7008d03c1cd161 100644 --- a/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM ubuntu:16.04 <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../cxx_deps.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/test/cxx_wheezy_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_wheezy_x64/Dockerfile.template deleted file mode 100644 index 5c38e9a0e924770fe2d1f6dde886aa94a288c57d..0000000000000000000000000000000000000000 --- a/templates/tools/dockerfile/test/cxx_wheezy_x64/Dockerfile.template +++ /dev/null @@ -1,56 +0,0 @@ -%YAML 1.2 ---- | - # Copyright 2016, Google Inc. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are - # met: - # - # * Redistributions of source code must retain the above copyright - # notice, this list of conditions and the following disclaimer. - # * Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following disclaimer - # in the documentation and/or other materials provided with the - # distribution. - # * Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - FROM debian:wheezy - - <%include file="../../apt_get_basic.include"/> - <%include file="../../python_deps.include"/> - <%include file="../../cxx_deps.include"/> - - RUN apt-get update && apt-get install -y ${'\\'} - gcc-4.4 ${'\\'} - gcc-4.4-multilib ${'\\'} - g++-4.4 ${'\\'} - g++-4.4-multilib - - # set up backport to allow installation of Git version > 1.7 - RUN echo "deb http://http.debian.net/debian wheezy-backports main" \ - >/etc/apt/sources.list.d/wheezy-backports.list - RUN apt-get update -qq - RUN apt-get -t wheezy-backports install -qq git - - RUN wget ${openssl_fallback.base_uri + openssl_fallback.tarball} - - ENV POST_GIT_STEP tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh - - <%include file="../../run_tests_addons.include"/> - # Define the default command. - CMD ["bash"] diff --git a/templates/tools/dockerfile/test/fuzzer/Dockerfile.template b/templates/tools/dockerfile/test/fuzzer/Dockerfile.template index 6d7cb72f2742f98a9c95d8bf7b09092fbb914b15..32a843a4823e49a54de3d330bb3059d3d5d7c0ed 100644 --- a/templates/tools/dockerfile/test/fuzzer/Dockerfile.template +++ b/templates/tools/dockerfile/test/fuzzer/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../cxx_deps.include"/> <%include file="../../clang_update.include"/> diff --git a/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template index 93d26b559453a99c04bf74451654fc3bd5cd0848..bf64ba210a95fe708ca806ad592ca08cc36ea157 100644 --- a/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../csharp_deps.include"/> <%include file="../../cxx_deps.include"/> <%include file="../../node_deps.include"/> diff --git a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template index ceaa9aa5abccbe880db12cfd64a407870f39066b..103b1ef848b2be3c99bf0ae83f94ca0dac5699fb 100644 --- a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> # Install Electron apt dependencies RUN apt-get update && apt-get install -y ${'\\'} diff --git a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template index e6a213d90d30f09517b2ffca0e93251dfad9d72d..158100283026bdcacb774e484fd40f10c0fb29ec 100644 --- a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../php7_deps.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. diff --git a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template index 0cfa373c9054090269036d0bbc718c58ce96086b..ced93d0406013bc3674714bf584da6e6588664fd 100644 --- a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../php_deps.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template index 46fb84ba830d6a1d6ae4e065cb3bced49b6208c7..26ff987ac23afbaabef7999775f259d34542c6b5 100644 --- a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template @@ -32,8 +32,8 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../run_tests_addons.include"/> # Define the default command. CMD ["bash"] - \ No newline at end of file diff --git a/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template index f9a4dcb7b6c30e3c83fed4db68bb7ee224e26f7e..62d9b92400bf60bbaf7c8b27dac9e6556dc1e5f6 100644 --- a/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../apt_get_pyenv.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template index 35838bc11e420dc57e19d93add5399f4487bad8d..d1899853e630ef2e212fef722dba3c40ee3d4308 100644 --- a/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template @@ -32,6 +32,7 @@ FROM debian:jessie <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> <%include file="../../ruby_deps.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template index 8617666b21eb2f36395794caf85fa90d4d330f5f..6943134b6a1994ccf3d64c1551895887f10aa1df 100644 --- a/templates/tools/dockerfile/test/sanity/Dockerfile.template +++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template @@ -32,6 +32,7 @@ FROM ubuntu:15.10 <%include file="../../apt_get_basic.include"/> + <%include file="../../gcp_api_libraries.include"/> <%include file="../../python_deps.include"/> #======================== # Sanity test dependencies diff --git a/templates/vsprojects/protoc.props.template b/templates/vsprojects/protoc.props.template index 2c3844a9a4e9af2a40c76e01abc3e26dfffffda6..65771fc5a3a57dc1f430d38be53e8fe8c12971e0 100644 --- a/templates/vsprojects/protoc.props.template +++ b/templates/vsprojects/protoc.props.template @@ -5,7 +5,7 @@ <PropertyGroup /> <ItemDefinitionGroup> <ClCompile> - <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <DisableSpecificWarnings>4244;4267;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/test/build/check_epollexclusive.c b/test/build/check_epollexclusive.c new file mode 100644 index 0000000000000000000000000000000000000000..fb512c3ae1adebe9f624a3a655d9a667a741dbbb --- /dev/null +++ b/test/build/check_epollexclusive.c @@ -0,0 +1,38 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/lib/iomgr/is_epollexclusive_available.h" + +int main(int argc, char **argv) { + return grpc_is_epollexclusive_available() ? 0 : 1; +} diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index 5eea5d43fe052111af55d4933596df834a725001..0fafb0c8c9979fe4294a11c28222d49f1b1c8512 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -77,7 +77,7 @@ struct cq_verifier { }; cq_verifier *cq_verifier_create(grpc_completion_queue *cq) { - cq_verifier *v = gpr_malloc(sizeof(cq_verifier)); + cq_verifier *v = (cq_verifier *)gpr_malloc(sizeof(cq_verifier)); v->cq = cq; v->first_expectation = NULL; return v; @@ -314,7 +314,7 @@ void cq_verify_empty(cq_verifier *v) { cq_verify_empty_timeout(v, 1); } static void add(cq_verifier *v, const char *file, int line, grpc_completion_type type, void *tag, bool success) { - expectation *e = gpr_malloc(sizeof(expectation)); + expectation *e = (expectation *)gpr_malloc(sizeof(expectation)); e->type = type; e->file = file; e->line = line; diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index 1187e59e6cc73228bdb048b5c348f865bb2b0228..4f0d11c3f57a42ca372bab8e09d09a6b36c34732 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -145,6 +145,8 @@ extern void streaming_error_response(grpc_end2end_test_config config); extern void streaming_error_response_pre_init(void); extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); +extern void workaround_cronet_compression(grpc_end2end_test_config config); +extern void workaround_cronet_compression_pre_init(void); extern void write_buffering(grpc_end2end_test_config config); extern void write_buffering_pre_init(void); extern void write_buffering_at_end(grpc_end2end_test_config config); @@ -204,6 +206,7 @@ void grpc_end2end_tests_pre_init(void) { simple_request_pre_init(); streaming_error_response_pre_init(); trailing_metadata_pre_init(); + workaround_cronet_compression_pre_init(); write_buffering_pre_init(); write_buffering_at_end_pre_init(); } @@ -265,6 +268,7 @@ void grpc_end2end_tests(int argc, char **argv, simple_request(config); streaming_error_response(config); trailing_metadata(config); + workaround_cronet_compression(config); write_buffering(config); write_buffering_at_end(config); return; @@ -471,6 +475,10 @@ void grpc_end2end_tests(int argc, char **argv, trailing_metadata(config); continue; } + if (0 == strcmp("workaround_cronet_compression", argv[i])) { + workaround_cronet_compression(config); + continue; + } if (0 == strcmp("write_buffering", argv[i])) { write_buffering(config); continue; diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index 966031af6571a4bc8f87bfb5e7acd1024fc8133f..9123d97b0e9ce0e0bdee32f2666057019709eb22 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -147,6 +147,8 @@ extern void streaming_error_response(grpc_end2end_test_config config); extern void streaming_error_response_pre_init(void); extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); +extern void workaround_cronet_compression(grpc_end2end_test_config config); +extern void workaround_cronet_compression_pre_init(void); extern void write_buffering(grpc_end2end_test_config config); extern void write_buffering_pre_init(void); extern void write_buffering_at_end(grpc_end2end_test_config config); @@ -207,6 +209,7 @@ void grpc_end2end_tests_pre_init(void) { simple_request_pre_init(); streaming_error_response_pre_init(); trailing_metadata_pre_init(); + workaround_cronet_compression_pre_init(); write_buffering_pre_init(); write_buffering_at_end_pre_init(); } @@ -269,6 +272,7 @@ void grpc_end2end_tests(int argc, char **argv, simple_request(config); streaming_error_response(config); trailing_metadata(config); + workaround_cronet_compression(config); write_buffering(config); write_buffering_at_end(config); return; @@ -479,6 +483,10 @@ void grpc_end2end_tests(int argc, char **argv, trailing_metadata(config); continue; } + if (0 == strcmp("workaround_cronet_compression", argv[i])) { + workaround_cronet_compression(config); + continue; + } if (0 == strcmp("write_buffering", argv[i])) { write_buffering(config); continue; diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c index df902a24bffa4bb1273681501e9ef15fc71c646e..736b224fd60e2fd68be5f94751c8ca8fe99c5595 100644 --- a/test/core/end2end/fake_resolver.c +++ b/test/core/end2end/fake_resolver.c @@ -136,7 +136,7 @@ struct grpc_fake_resolver_response_generator { grpc_fake_resolver_response_generator* grpc_fake_resolver_response_generator_create() { grpc_fake_resolver_response_generator* generator = - gpr_zalloc(sizeof(*generator)); + (grpc_fake_resolver_response_generator*)gpr_zalloc(sizeof(*generator)); gpr_ref_init(&generator->refcount, 1); return generator; } @@ -157,7 +157,8 @@ void grpc_fake_resolver_response_generator_unref( static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - grpc_fake_resolver_response_generator* generator = arg; + grpc_fake_resolver_response_generator* generator = + (grpc_fake_resolver_response_generator*)arg; fake_resolver* r = generator->resolver; if (r->next_results != NULL) { grpc_channel_args_destroy(exec_ctx, r->next_results); @@ -180,11 +181,13 @@ void grpc_fake_resolver_response_generator_set_response( } static void* response_generator_arg_copy(void* p) { - return grpc_fake_resolver_response_generator_ref(p); + return grpc_fake_resolver_response_generator_ref( + (grpc_fake_resolver_response_generator*)p); } static void response_generator_arg_destroy(grpc_exec_ctx* exec_ctx, void* p) { - grpc_fake_resolver_response_generator_unref(p); + grpc_fake_resolver_response_generator_unref( + (grpc_fake_resolver_response_generator*)p); } static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); } @@ -208,7 +211,7 @@ grpc_fake_resolver_get_response_generator(const grpc_channel_args* args) { const grpc_arg* arg = grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR); if (arg == NULL || arg->type != GRPC_ARG_POINTER) return NULL; - return arg->value.pointer.p; + return (grpc_fake_resolver_response_generator*)arg->value.pointer.p; } // @@ -222,7 +225,7 @@ static void fake_resolver_factory_unref(grpc_resolver_factory* factory) {} static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_args* args) { - fake_resolver* r = gpr_zalloc(sizeof(*r)); + fake_resolver* r = (fake_resolver*)gpr_zalloc(sizeof(*r)); r->channel_args = grpc_channel_args_copy(args->args); grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner); grpc_fake_resolver_response_generator* response_generator = diff --git a/test/core/end2end/fixtures/h2_full+workarounds.c b/test/core/end2end/fixtures/h2_full+workarounds.c index cc86c3abf36054a69d0fc000776b3a7829f6ed68..2e9264ffa6357eeb5a8bda4cbf8a37f4b16b1f6a 100644 --- a/test/core/end2end/fixtures/h2_full+workarounds.c +++ b/test/core/end2end/fixtures/h2_full+workarounds.c @@ -41,6 +41,7 @@ #include <grpc/support/sync.h> #include <grpc/support/thd.h> #include <grpc/support/useful.h> +#include <grpc/support/workaround_list.h> #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/http/server/http_server_filter.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" @@ -50,10 +51,8 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -/* List the workarounds to be enabled */ -static char *workarounds_enabled[] = {GRPC_ARG_WORKAROUND_CRONET_COMPRESSION}; -static const size_t workarounds_num = - sizeof(workarounds_enabled) / sizeof(*workarounds_enabled); +static char *workarounds_arg[GRPC_MAX_WORKAROUND_ID] = { + GRPC_ARG_WORKAROUND_CRONET_COMPRESSION}; typedef struct fullstack_fixture_data { char *localaddr; @@ -86,14 +85,14 @@ void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; fullstack_fixture_data *ffd = f->fixture_data; - grpc_arg args[workarounds_num]; - for (uint32_t i = 0; i < workarounds_num; i++) { - args[i].key = workarounds_enabled[i]; + grpc_arg args[GRPC_MAX_WORKAROUND_ID]; + for (uint32_t i = 0; i < GRPC_MAX_WORKAROUND_ID; i++) { + args[i].key = workarounds_arg[i]; args[i].type = GRPC_ARG_INTEGER; args[i].value.integer = 1; } grpc_channel_args *server_args_new = - grpc_channel_args_copy_and_add(server_args, args, workarounds_num); + grpc_channel_args_copy_and_add(server_args, args, GRPC_MAX_WORKAROUND_ID); if (f->server) { grpc_server_destroy(f->server); } diff --git a/test/core/end2end/fixtures/http_proxy_fixture.c b/test/core/end2end/fixtures/http_proxy_fixture.c index f0d09487c62d215db91fb78748b917e2b0685e06..c2d8480e69a2e38005d5e9add9d3afe79a86f82b 100644 --- a/test/core/end2end/fixtures/http_proxy_fixture.c +++ b/test/core/end2end/fixtures/http_proxy_fixture.c @@ -156,7 +156,7 @@ static void proxy_connection_failed(grpc_exec_ctx* exec_ctx, // Callback for writing proxy data to the client. static void on_client_write_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy client write", error); @@ -181,7 +181,7 @@ static void on_client_write_done(grpc_exec_ctx* exec_ctx, void* arg, // Callback for writing proxy data to the backend server. static void on_server_write_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, false /* is_client */, "HTTP proxy server write", error); @@ -207,7 +207,7 @@ static void on_server_write_done(grpc_exec_ctx* exec_ctx, void* arg, // the backend server. static void on_client_read_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy client read", error); @@ -239,7 +239,7 @@ static void on_client_read_done(grpc_exec_ctx* exec_ctx, void* arg, // proxied to the client. static void on_server_read_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, false /* is_client */, "HTTP proxy server read", error); @@ -270,7 +270,7 @@ static void on_server_read_done(grpc_exec_ctx* exec_ctx, void* arg, // Callback to write the HTTP response for the CONNECT request. static void on_write_response_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; if (error != GRPC_ERROR_NONE) { proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy write response", error); @@ -294,7 +294,7 @@ static void on_write_response_done(grpc_exec_ctx* exec_ctx, void* arg, // CONNECT request. static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; if (error != GRPC_ERROR_NONE) { // TODO(roth): Technically, in this case, we should handle the error // by returning an HTTP response to the client indicating that the @@ -324,7 +324,7 @@ static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, // which will cause the client connection to be dropped. static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - proxy_connection* conn = arg; + proxy_connection* conn = (proxy_connection*)arg; gpr_log(GPR_DEBUG, "on_read_request_done: %p %s", conn, grpc_error_string(error)); if (error != GRPC_ERROR_NONE) { @@ -389,9 +389,9 @@ static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, grpc_endpoint* endpoint, grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor) { gpr_free(acceptor); - grpc_end2end_http_proxy* proxy = arg; + grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)arg; // Instantiate proxy_connection. - proxy_connection* conn = gpr_zalloc(sizeof(*conn)); + proxy_connection* conn = (proxy_connection*)gpr_zalloc(sizeof(*conn)); gpr_ref(&proxy->users); conn->client_endpoint = endpoint; conn->proxy = proxy; @@ -430,7 +430,7 @@ static void on_accept(grpc_exec_ctx* exec_ctx, void* arg, // static void thread_main(void* arg) { - grpc_end2end_http_proxy* proxy = arg; + grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)arg; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; do { gpr_ref(&proxy->users); @@ -450,7 +450,8 @@ static void thread_main(void* arg) { grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_end2end_http_proxy* proxy = gpr_malloc(sizeof(*proxy)); + grpc_end2end_http_proxy* proxy = + (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy)); memset(proxy, 0, sizeof(*proxy)); gpr_ref_init(&proxy->users, 1); // Construct proxy address. @@ -473,7 +474,7 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) { GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(port == proxy_port); // Start server. - proxy->pollset = gpr_zalloc(grpc_pollset_size()); + proxy->pollset = (grpc_pollset*)gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(proxy->pollset, &proxy->mu); grpc_tcp_server_start(&exec_ctx, proxy->server, &proxy->pollset, 1, on_accept, proxy); @@ -487,8 +488,8 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) { static void destroy_pollset(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { - grpc_pollset* pollset = arg; - grpc_pollset_destroy(pollset); + grpc_pollset* pollset = (grpc_pollset*)arg; + grpc_pollset_destroy(exec_ctx, pollset); gpr_free(pollset); } diff --git a/test/core/end2end/fuzzers/api_fuzzer.c b/test/core/end2end/fuzzers/api_fuzzer.c index 88a0e301da166c0b1e4bd531dae3150bbc95bdf4..b33b43dac587fad86765107f8dc3220414f16633 100644 --- a/test/core/end2end/fuzzers/api_fuzzer.c +++ b/test/core/end2end/fuzzers/api_fuzzer.c @@ -44,6 +44,7 @@ #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/iomgr/timer_manager.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/server.h" #include "src/core/lib/transport/metadata.h" @@ -722,6 +723,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_tcp_client_connect_impl = my_tcp_client_connect; gpr_now_impl = now_impl; grpc_init(); + grpc_timer_manager_set_threading(false); grpc_resolve_address = my_resolve_address; GPR_ASSERT(g_channel == NULL); @@ -769,6 +771,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN)); } + grpc_timer_manager_tick(); + switch (next_byte(&inp)) { // terminate on bad bytes default: diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index cb50a82cee718981622b37e79769fa97beef52e8..34b5938288acea20610d295500fa5a777bb6933c 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -152,6 +152,7 @@ END2END_TESTS = { 'simple_request': default_test_options, 'streaming_error_response': default_test_options._replace(cpu_cost=LOWCPU), 'trailing_metadata': default_test_options, + 'workaround_cronet_compression': default_test_options, 'write_buffering': default_test_options._replace(cpu_cost=LOWCPU), 'write_buffering_at_end': default_test_options._replace(cpu_cost=LOWCPU), } diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index dc0925dc9c03bfffa7d6ea0904127e0bfd04f8df..e14157849fb285547e7007ee268acebdd6148515 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -65,7 +65,7 @@ END2END_FIXTURES = { tracing=True), 'h2_ssl': fixture_options(secure=True), 'h2_ssl_cert': fixture_options(secure=True), - 'h2_ssl_proxy': fixture_options(secure=True), + 'h2_ssl_proxy': fixture_options(includes_proxy=True, secure=True), 'h2_uds': fixture_options(dns_resolver=False, platforms=['linux', 'mac', 'posix']), } @@ -95,7 +95,7 @@ END2END_TESTS = { 'cancel_before_invoke': test_options(), 'cancel_in_a_vacuum': test_options(), 'cancel_with_status': test_options(), - 'compressed_payload': test_options(), + 'compressed_payload': test_options(proxyable=False), 'connectivity': test_options(needs_fullstack=True, proxyable=False), 'default_host': test_options(needs_fullstack=True, needs_dns=True), 'disappearing_server': test_options(needs_fullstack=True), @@ -120,7 +120,7 @@ END2END_TESTS = { 'payload': test_options(), 'load_reporting_hook': test_options(), 'ping_pong_streaming': test_options(), - 'ping': test_options(proxyable=False), + 'ping': test_options(needs_fullstack=True, proxyable=False), 'registered_call': test_options(), 'request_with_flags': test_options(proxyable=False), 'request_with_payload': test_options(), diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index 5bc9ed283bb6d01f08b7b8889da91aa924fd755f..6deb86ea3e49a239aea564bba4af867018566385 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -147,6 +147,11 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, op->flags = 0; op->reserved = NULL; op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; @@ -161,11 +166,6 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, op->flags = 0; op->reserved = NULL; op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; - op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; - op->flags = 0; - op->reserved = NULL; - op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &response_payload_recv; op->flags = 0; @@ -200,7 +200,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, void cancel_after_invoke(grpc_end2end_test_config config) { unsigned i, j; - for (j = 2; j < 6; j++) { + for (j = 3; j < 6; j++) { for (i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); i++) { test_cancel_after_invoke(config, cancellation_modes[i], j); } diff --git a/test/core/end2end/tests/compressed_payload.c b/test/core/end2end/tests/compressed_payload.c index e96d8a9b71e5f78abfc7711a0ce39364576f183d..1fe8613adbef968f5266d4aaaeba5f44234242b0 100644 --- a/test/core/end2end/tests/compressed_payload.c +++ b/test/core/end2end/tests/compressed_payload.c @@ -289,8 +289,7 @@ static void request_with_payload_template( grpc_compression_algorithm expected_algorithm_from_client, grpc_compression_algorithm expected_algorithm_from_server, grpc_metadata *client_init_metadata, bool set_server_level, - grpc_compression_level server_compression_level, - char *user_agent_override) { + grpc_compression_level server_compression_level) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice; @@ -330,18 +329,6 @@ static void request_with_payload_template( server_args = grpc_channel_args_set_compression_algorithm( NULL, default_server_channel_compression_algorithm); - if (user_agent_override) { - grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - grpc_channel_args *client_args_old = client_args; - grpc_arg arg; - arg.key = GRPC_ARG_PRIMARY_USER_AGENT_STRING; - arg.type = GRPC_ARG_STRING; - arg.value.string = user_agent_override; - client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1); - grpc_channel_args_destroy(&exec_ctx, client_args_old); - grpc_exec_ctx_finish(&exec_ctx); - } - f = begin_test(config, test_name, client_args, server_args); cqv = cq_verifier_create(f.cq); @@ -554,7 +541,7 @@ static void test_invoke_request_with_exceptionally_uncompressed_payload( config, "test_invoke_request_with_exceptionally_uncompressed_payload", GRPC_WRITE_NO_COMPRESS, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, NULL, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, NULL); + /* ignored */ GRPC_COMPRESS_LEVEL_NONE); } static void test_invoke_request_with_uncompressed_payload( @@ -562,8 +549,7 @@ static void test_invoke_request_with_uncompressed_payload( request_with_payload_template( config, "test_invoke_request_with_uncompressed_payload", 0, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, - GRPC_COMPRESS_NONE, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - NULL); + GRPC_COMPRESS_NONE, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE); } static void test_invoke_request_with_compressed_payload( @@ -571,8 +557,7 @@ static void test_invoke_request_with_compressed_payload( request_with_payload_template( config, "test_invoke_request_with_compressed_payload", 0, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - NULL); + GRPC_COMPRESS_GZIP, NULL, false, /* ignored */ GRPC_COMPRESS_LEVEL_NONE); } static void test_invoke_request_with_server_level( @@ -580,7 +565,7 @@ static void test_invoke_request_with_server_level( request_with_payload_template( config, "test_invoke_request_with_server_level", 0, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE /* ignored */, - NULL, true, GRPC_COMPRESS_LEVEL_HIGH, NULL); + NULL, true, GRPC_COMPRESS_LEVEL_HIGH); } static void test_invoke_request_with_compressed_payload_md_override( @@ -604,21 +589,21 @@ static void test_invoke_request_with_compressed_payload_md_override( config, "test_invoke_request_with_compressed_payload_md_override_1", 0, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_NONE, &gzip_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, NULL); + /*ignored*/ GRPC_COMPRESS_LEVEL_NONE); /* Channel default DEFLATE, call override to GZIP */ request_with_payload_template( config, "test_invoke_request_with_compressed_payload_md_override_2", 0, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_NONE, &gzip_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, NULL); + /*ignored*/ GRPC_COMPRESS_LEVEL_NONE); /* Channel default DEFLATE, call override to NONE (aka IDENTITY) */ request_with_payload_template( config, "test_invoke_request_with_compressed_payload_md_override_3", 0, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE, &identity_compression_override, false, - /*ignored*/ GRPC_COMPRESS_LEVEL_NONE, NULL); + /*ignored*/ GRPC_COMPRESS_LEVEL_NONE); } static void test_invoke_request_with_disabled_algorithm( @@ -628,34 +613,6 @@ static void test_invoke_request_with_disabled_algorithm( GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_STATUS_UNIMPLEMENTED, NULL); } -typedef struct workaround_cronet_compression_config { - char *user_agent_override; - grpc_compression_algorithm expected_algorithm_from_server; -} workaround_cronet_compression_config; - -static workaround_cronet_compression_config workaround_configs[] = { - {NULL, GRPC_COMPRESS_GZIP}, - {"grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; cronet_http; gentle)", - GRPC_COMPRESS_NONE}, - {"grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; chttp2; gentle)", - GRPC_COMPRESS_GZIP}, - {"grpc-objc/1.4.0 grpc-c/3.0.0-dev (ios; cronet_http; gentle)", - GRPC_COMPRESS_GZIP}}; -static const size_t workaround_configs_num = - sizeof(workaround_configs) / sizeof(*workaround_configs); - -static void test_workaround_cronet_compression( - grpc_end2end_test_config config) { - for (uint32_t i = 0; i < workaround_configs_num; i++) { - request_with_payload_template( - config, "test_invoke_request_with_compressed_payload", 0, - GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, - workaround_configs[i].expected_algorithm_from_server, NULL, false, - /* ignored */ GRPC_COMPRESS_LEVEL_NONE, - workaround_configs[i].user_agent_override); - } -} - void compressed_payload(grpc_end2end_test_config config) { test_invoke_request_with_exceptionally_uncompressed_payload(config); test_invoke_request_with_uncompressed_payload(config); @@ -663,9 +620,6 @@ void compressed_payload(grpc_end2end_test_config config) { test_invoke_request_with_server_level(config); test_invoke_request_with_compressed_payload_md_override(config); test_invoke_request_with_disabled_algorithm(config); - if (config.feature_mask & FEATURE_MASK_SUPPORTS_WORKAROUNDS) { - test_workaround_cronet_compression(config); - } } void compressed_payload_pre_init(void) {} diff --git a/test/core/end2end/tests/workaround_cronet_compression.c b/test/core/end2end/tests/workaround_cronet_compression.c new file mode 100644 index 0000000000000000000000000000000000000000..f8ce8c50c4e569343cb56dcc46d8973923d9b827 --- /dev/null +++ b/test/core/end2end/tests/workaround_cronet_compression.c @@ -0,0 +1,411 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/byte_buffer_reader.h> +#include <grpc/compression.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/string_util.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/surface/call.h" +#include "src/core/lib/surface/call_test_only.h" +#include "src/core/lib/transport/static_metadata.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void request_with_payload_template( + grpc_end2end_test_config config, const char *test_name, + uint32_t client_send_flags_bitmask, + grpc_compression_algorithm default_client_channel_compression_algorithm, + grpc_compression_algorithm default_server_channel_compression_algorithm, + grpc_compression_algorithm expected_algorithm_from_client, + grpc_compression_algorithm expected_algorithm_from_server, + grpc_metadata *client_init_metadata, bool set_server_level, + grpc_compression_level server_compression_level, + char *user_agent_override) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice; + grpc_byte_buffer *request_payload; + grpc_channel_args *client_args; + grpc_channel_args *server_args; + grpc_end2end_test_fixture f; + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer *request_payload_recv = NULL; + grpc_byte_buffer *response_payload; + grpc_byte_buffer *response_payload_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + cq_verifier *cqv; + char request_str[1024]; + char response_str[1024]; + + memset(request_str, 'x', 1023); + request_str[1023] = '\0'; + + memset(response_str, 'y', 1023); + response_str[1023] = '\0'; + + request_payload_slice = grpc_slice_from_copied_string(request_str); + grpc_slice response_payload_slice = + grpc_slice_from_copied_string(response_str); + + client_args = grpc_channel_args_set_compression_algorithm( + NULL, default_client_channel_compression_algorithm); + server_args = grpc_channel_args_set_compression_algorithm( + NULL, default_server_channel_compression_algorithm); + + if (user_agent_override) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args *client_args_old = client_args; + grpc_arg arg; + arg.key = GRPC_ARG_PRIMARY_USER_AGENT_STRING; + arg.type = GRPC_ARG_STRING; + arg.value.string = user_agent_override; + client_args = grpc_channel_args_copy_and_add(client_args_old, &arg, 1); + grpc_channel_args_destroy(&exec_ctx, client_args_old); + grpc_exec_ctx_finish(&exec_ctx); + } + + f = begin_test(config, test_name, client_args, server_args); + cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + if (client_init_metadata != NULL) { + op->data.send_initial_metadata.count = 1; + op->data.send_initial_metadata.metadata = client_init_metadata; + } else { + op->data.send_initial_metadata.count = 0; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(100)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(100), true); + cq_verify(cqv); + + GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( + s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_NONE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_DEFLATE) != 0); + GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), + GRPC_COMPRESS_GZIP) != 0); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + if (set_server_level) { + op->data.send_initial_metadata.maybe_compression_level.is_set = true; + op->data.send_initial_metadata.maybe_compression_level.level = + server_compression_level; + } + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(101), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + for (int i = 0; i < 2; i++) { + request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); + response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op->flags = client_send_flags_bitmask; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &request_payload_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + cq_verify(cqv); + + GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); + GPR_ASSERT(request_payload_recv->data.raw.compression == + expected_algorithm_from_client); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = response_payload; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(103), 1); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv); + + GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); + GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); + if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { + const grpc_compression_algorithm algo_for_server_level = + grpc_call_compression_for_level(s, server_compression_level); + GPR_ASSERT(response_payload_recv->data.raw.compression == + algo_for_server_level); + } else { + GPR_ASSERT(response_payload_recv->data.raw.compression == + expected_algorithm_from_server); + } + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + } + + grpc_slice_unref(request_payload_slice); + grpc_slice_unref(response_payload_slice); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + CQ_EXPECT_COMPLETION(cqv, tag(3), 1); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + CQ_EXPECT_COMPLETION(cqv, tag(104), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); + + { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_channel_args_destroy(&exec_ctx, client_args); + grpc_channel_args_destroy(&exec_ctx, server_args); + grpc_exec_ctx_finish(&exec_ctx); + } + + end_test(&f); + config.tear_down_data(&f); +} + +typedef struct workaround_cronet_compression_config { + char *user_agent_override; + grpc_compression_algorithm expected_algorithm_from_server; +} workaround_cronet_compression_config; + +static workaround_cronet_compression_config workaround_configs[] = { + {NULL, GRPC_COMPRESS_GZIP}, + {"grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; cronet_http; gentle)", + GRPC_COMPRESS_NONE}, + {"grpc-objc/1.3.0-dev grpc-c/3.0.0-dev (ios; chttp2; gentle)", + GRPC_COMPRESS_GZIP}, + {"grpc-objc/1.4.0 grpc-c/3.0.0-dev (ios; cronet_http; gentle)", + GRPC_COMPRESS_GZIP}}; +static const size_t workaround_configs_num = + sizeof(workaround_configs) / sizeof(*workaround_configs); + +static void test_workaround_cronet_compression( + grpc_end2end_test_config config) { + for (uint32_t i = 0; i < workaround_configs_num; i++) { + request_with_payload_template( + config, "test_invoke_request_with_compressed_payload", 0, + GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, GRPC_COMPRESS_GZIP, + workaround_configs[i].expected_algorithm_from_server, NULL, false, + /* ignored */ GRPC_COMPRESS_LEVEL_NONE, + workaround_configs[i].user_agent_override); + } +} + +void workaround_cronet_compression(grpc_end2end_test_config config) { + if (config.feature_mask & FEATURE_MASK_SUPPORTS_WORKAROUNDS) { + test_workaround_cronet_compression(config); + } +} + +void workaround_cronet_compression_pre_init(void) {} diff --git a/test/core/http/httpcli_test.c b/test/core/http/httpcli_test.c index d3b45c45056da5c6fc1554521c1b8c0daacb3159..21135ddf6b1d19610a47e1c0072460d98fd69891 100644 --- a/test/core/http/httpcli_test.c +++ b/test/core/http/httpcli_test.c @@ -155,7 +155,7 @@ static void test_post(int port) { } static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(grpc_polling_entity_pollset(p)); + grpc_pollset_destroy(exec_ctx, grpc_polling_entity_pollset(p)); } int main(int argc, char **argv) { diff --git a/test/core/http/httpscli_test.c b/test/core/http/httpscli_test.c index acc94091f4e44f1317748ce92fc2851ac54f6d5d..73eaae87d75bc00afc6760001d207fe3dae3871d 100644 --- a/test/core/http/httpscli_test.c +++ b/test/core/http/httpscli_test.c @@ -157,7 +157,7 @@ static void test_post(int port) { } static void destroy_pops(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(grpc_polling_entity_pollset(p)); + grpc_pollset_destroy(exec_ctx, grpc_polling_entity_pollset(p)); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 0cf93e73f5c3b45f496ce9658abc685f011f14e6..808faf57c9d48ba79886f4351518ee751d623b23 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -55,8 +55,8 @@ cc_test( ) cc_test( - name = "ev_epoll_linux_test", - srcs = ["ev_epoll_linux_test.c"], + name = "ev_epollsig_linux_test", + srcs = ["ev_epollsig_linux_test.c"], deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"], copts = ['-std=c99'] ) diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c index c8a60776b9c7b9ae5a72c1bffad25d558459f5a9..4561c3846e1696f2f18c83ced1f11a5fcc575326 100644 --- a/test/core/iomgr/endpoint_pair_test.c +++ b/test/core/iomgr/endpoint_pair_test.c @@ -70,7 +70,7 @@ static grpc_endpoint_test_config configs[] = { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/ev_epoll_linux_test.c b/test/core/iomgr/ev_epollsig_linux_test.c similarity index 98% rename from test/core/iomgr/ev_epoll_linux_test.c rename to test/core/iomgr/ev_epollsig_linux_test.c index 0856023b14f6878483836515327609c64399cf51..45c542de4e4e1f95ce5095da751205cef16a2f2f 100644 --- a/test/core/iomgr/ev_epoll_linux_test.c +++ b/test/core/iomgr/ev_epollsig_linux_test.c @@ -34,7 +34,7 @@ /* This test only relevant on linux systems where epoll() is available */ #ifdef GRPC_LINUX_EPOLL -#include "src/core/lib/iomgr/ev_epoll_linux.h" +#include "src/core/lib/iomgr/ev_epollsig_linux.h" #include "src/core/lib/iomgr/ev_posix.h" #include <errno.h> @@ -113,7 +113,7 @@ static void test_pollset_init(test_pollset *pollsets, int num_pollsets) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } static void test_pollset_cleanup(grpc_exec_ctx *exec_ctx, @@ -403,15 +403,16 @@ int main(int argc, char **argv) { const char *poll_strategy = NULL; grpc_test_init(argc, argv); grpc_iomgr_init(); + grpc_iomgr_start(); poll_strategy = grpc_get_poll_strategy_name(); - if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) { + if (poll_strategy != NULL && strcmp(poll_strategy, "epollsig") == 0) { test_add_fd_to_pollset(); test_pollset_queue_merge_items(); test_threading(); } else { gpr_log(GPR_INFO, - "Skipping the test. The test is only relevant for 'epoll' " + "Skipping the test. The test is only relevant for 'epollsig' " "strategy. and the current strategy is: '%s'", poll_strategy); } diff --git a/test/core/iomgr/fd_conservation_posix_test.c b/test/core/iomgr/fd_conservation_posix_test.c index 6ac322bb01458f8532dd955f14bc50958e4a6384..f66207065598cf94924682c584d87042f64cf1d3 100644 --- a/test/core/iomgr/fd_conservation_posix_test.c +++ b/test/core/iomgr/fd_conservation_posix_test.c @@ -46,6 +46,7 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_iomgr_init(); + grpc_iomgr_start(); /* set max # of file descriptors to a low value, and verify we can create and destroy many more than this number diff --git a/test/core/iomgr/fd_posix_test.c b/test/core/iomgr/fd_posix_test.c index 81d2692a084c05d467f4bca7a312ceaae3e07891..9e8fe8bffade74920ab4d622f3b3b654d30465e8 100644 --- a/test/core/iomgr/fd_posix_test.c +++ b/test/core/iomgr/fd_posix_test.c @@ -535,7 +535,7 @@ static void test_grpc_fd_change(void) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { @@ -543,6 +543,7 @@ int main(int argc, char **argv) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_test_init(argc, argv); grpc_iomgr_init(); + grpc_iomgr_start(); g_pollset = gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(g_pollset, &g_mu); test_grpc_fd(); diff --git a/test/core/iomgr/pollset_set_test.c b/test/core/iomgr/pollset_set_test.c index 3a9d459579f53394dd8f6510354f82c8953029fd..092711381d1cf0fea6fea98cd187f8edf3f4dc81 100644 --- a/test/core/iomgr/pollset_set_test.c +++ b/test/core/iomgr/pollset_set_test.c @@ -86,7 +86,7 @@ static void init_test_pollsets(test_pollset *pollsets, const int num_pollsets) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } static void cleanup_test_pollsets(grpc_exec_ctx *exec_ctx, @@ -448,8 +448,11 @@ int main(int argc, char **argv) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_test_init(argc, argv); grpc_iomgr_init(); + grpc_iomgr_start(); - if (poll_strategy != NULL && strcmp(poll_strategy, "epoll") == 0) { + if (poll_strategy != NULL && + (strcmp(poll_strategy, "epoll") == 0 || + strcmp(poll_strategy, "epoll-threadpool") == 0)) { pollset_set_test_basic(); pollset_set_test_dup_fds(); pollset_set_test_empty_pollset(); diff --git a/test/core/iomgr/resolve_address_posix_test.c b/test/core/iomgr/resolve_address_posix_test.c index fa88aca431f37beee251b4cc50be42b0126555ef..bee7036ec83328bfee488f10e44f505126b3ea74 100644 --- a/test/core/iomgr/resolve_address_posix_test.c +++ b/test/core/iomgr/resolve_address_posix_test.c @@ -81,7 +81,7 @@ void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb); // exec_ctx needs to be flushed before calling grpc_pollset_destroy() grpc_exec_ctx_flush(exec_ctx); - grpc_pollset_destroy(args->pollset); + grpc_pollset_destroy(exec_ctx, args->pollset); gpr_free(args->pollset); } @@ -176,6 +176,7 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_executor_init(); grpc_iomgr_init(); + grpc_iomgr_start(); test_unix_socket(); test_unix_socket_path_name_too_long(); { diff --git a/test/core/iomgr/resolve_address_test.c b/test/core/iomgr/resolve_address_test.c index ea79adc0903f2f08974275235cf4ff00058dbe10..83f73070dcc6ad15ef3b4b0ba9a0e8a760e45232 100644 --- a/test/core/iomgr/resolve_address_test.c +++ b/test/core/iomgr/resolve_address_test.c @@ -76,7 +76,7 @@ void args_finish(grpc_exec_ctx *exec_ctx, args_struct *args) { grpc_pollset_shutdown(exec_ctx, args->pollset, &do_nothing_cb); // exec_ctx needs to be flushed before calling grpc_pollset_destroy() grpc_exec_ctx_flush(exec_ctx); - grpc_pollset_destroy(args->pollset); + grpc_pollset_destroy(exec_ctx, args->pollset); gpr_free(args->pollset); } @@ -265,6 +265,7 @@ int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_executor_init(); grpc_iomgr_init(); + grpc_iomgr_start(); test_localhost(); test_default_port(); test_non_numeric_default_port(); diff --git a/test/core/iomgr/tcp_client_posix_test.c b/test/core/iomgr/tcp_client_posix_test.c index 2fae6774e869953370c53e3f6e67cb2cb4a8ac16..6e1bb43eb5b853ae99055d16c79b81297656760a 100644 --- a/test/core/iomgr/tcp_client_posix_test.c +++ b/test/core/iomgr/tcp_client_posix_test.c @@ -197,7 +197,7 @@ void test_fails(void) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c index 92fc3934226deb992c18b320004a3e6ed335c31d..3a8458df861a03baa77a35c13cbc15ed37f2581a 100644 --- a/test/core/iomgr/tcp_client_uv_test.c +++ b/test/core/iomgr/tcp_client_uv_test.c @@ -194,7 +194,7 @@ void test_fails(void) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 2c53a003d23a83dd86a57866c6ca9e1c8ab2ae47..a1c54e19c1c3b3b27479fa4b73c79e49697dde11 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -562,7 +562,7 @@ static grpc_endpoint_test_config configs[] = { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c index 112743b95b723a27246dfb82c7a144ba7699f76f..88aead1dd0d96112932f64b98997fad64cfdc6ed 100644 --- a/test/core/iomgr/tcp_server_posix_test.c +++ b/test/core/iomgr/tcp_server_posix_test.c @@ -444,7 +444,7 @@ static void test_connect(size_t num_connects, static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c index 1e039585c1e8dae2e738ef148de95a300dad2eee..945b84a355c66aad5db3195c349551564eaed295 100644 --- a/test/core/iomgr/tcp_server_uv_test.c +++ b/test/core/iomgr/tcp_server_uv_test.c @@ -306,7 +306,7 @@ static void test_connect(unsigned n) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/iomgr/timer_list_test.c b/test/core/iomgr/timer_list_test.c index 46e41dd4490bc320b39d42fb3af32e3180e9d415..88a9f6b855678c16dc24d6db34f0542ce169b5a4 100644 --- a/test/core/iomgr/timer_list_test.c +++ b/test/core/iomgr/timer_list_test.c @@ -41,12 +41,13 @@ #include <string.h> #include <grpc/support/log.h> +#include "src/core/lib/debug/trace.h" #include "test/core/util/test_config.h" #define MAX_CB 30 -extern int grpc_timer_trace; -extern int grpc_timer_check_trace; +extern grpc_tracer_flag grpc_timer_trace; +extern grpc_tracer_flag grpc_timer_check_trace; static int cb_called[MAX_CB][2]; @@ -63,8 +64,8 @@ static void add_test(void) { gpr_log(GPR_INFO, "add_test"); grpc_timer_list_init(start); - grpc_timer_trace = 1; - grpc_timer_check_trace = 1; + grpc_timer_trace.value = 1; + grpc_timer_check_trace.value = 1; memset(cb_called, 0, sizeof(cb_called)); /* 10 ms timers. will expire in the current epoch */ @@ -138,8 +139,8 @@ void destruction_test(void) { gpr_log(GPR_INFO, "destruction_test"); grpc_timer_list_init(gpr_time_0(GPR_CLOCK_REALTIME)); - grpc_timer_trace = 1; - grpc_timer_check_trace = 1; + grpc_timer_trace.value = 1; + grpc_timer_check_trace.value = 1; memset(cb_called, 0, sizeof(cb_called)); grpc_timer_init( diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c index 1f1696a7a7a0b86cf1a4c54d03268ff10c536bb4..ee78d6b4adf2ae4530230757b923827942ce3792 100644 --- a/test/core/iomgr/udp_server_test.c +++ b/test/core/iomgr/udp_server_test.c @@ -307,7 +307,7 @@ static void test_receive(int number_of_clients) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/security/oauth2_utils.c b/test/core/security/oauth2_utils.c index f0550db1d06b2c358e0941186381e2358e4dfcea..838625705dda694b46ed608a8ffe66988ccc366f 100644 --- a/test/core/security/oauth2_utils.c +++ b/test/core/security/oauth2_utils.c @@ -55,7 +55,7 @@ static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status, const char *error_details) { - oauth2_request *request = user_data; + oauth2_request *request = (oauth2_request *)user_data; char *token = NULL; grpc_slice token_slice; if (status == GRPC_CREDENTIALS_ERROR) { @@ -63,7 +63,7 @@ static void on_oauth2_response(grpc_exec_ctx *exec_ctx, void *user_data, } else { GPR_ASSERT(num_md == 1); token_slice = md_elems[0].value; - token = gpr_malloc(GRPC_SLICE_LENGTH(token_slice) + 1); + token = (char *)gpr_malloc(GRPC_SLICE_LENGTH(token_slice) + 1); memcpy(token, GRPC_SLICE_START_PTR(token_slice), GRPC_SLICE_LENGTH(token_slice)); token[GRPC_SLICE_LENGTH(token_slice)] = '\0'; @@ -87,7 +87,7 @@ char *grpc_test_fetch_oauth2_token_with_credentials( grpc_closure do_nothing_closure; grpc_auth_metadata_context null_ctx = {"", "", NULL, NULL}; - grpc_pollset *pollset = gpr_zalloc(grpc_pollset_size()); + grpc_pollset *pollset = (grpc_pollset *)gpr_zalloc(grpc_pollset_size()); grpc_pollset_init(pollset, &request.mu); request.pops = grpc_polling_entity_create_from_pollset(pollset); request.is_done = 0; diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index 71d8057ac3140b74d3c6712ccb835675b74e4588..cd6ff2ceacf121f2c869d79185e7d5c840485608 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -185,7 +185,7 @@ static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { static void destroy_pollset(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { - grpc_pollset_destroy(p); + grpc_pollset_destroy(exec_ctx, p); } int main(int argc, char **argv) { diff --git a/test/core/surface/concurrent_connectivity_test.c b/test/core/surface/concurrent_connectivity_test.c index d6841ea1f881b4328ac678851748b466eccabf19..f0e3394b2e73f6222948db31782df6378442d15b 100644 --- a/test/core/surface/concurrent_connectivity_test.c +++ b/test/core/surface/concurrent_connectivity_test.c @@ -162,7 +162,7 @@ void bad_server_thread(void *vargs) { static void done_pollset_shutdown(grpc_exec_ctx *exec_ctx, void *pollset, grpc_error *error) { - grpc_pollset_destroy(pollset); + grpc_pollset_destroy(exec_ctx, pollset); gpr_free(pollset); } diff --git a/test/core/transport/bdp_estimator_test.c b/test/core/transport/bdp_estimator_test.c index f55a3ca64391e7622b29ffe159a8d9574476e809..a6f1a5536336ea8440119acdf8327faafd778912 100644 --- a/test/core/transport/bdp_estimator_test.c +++ b/test/core/transport/bdp_estimator_test.c @@ -33,6 +33,7 @@ #include "src/core/lib/transport/bdp_estimator.h" +#include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> @@ -64,6 +65,8 @@ static void add_samples(grpc_bdp_estimator *estimator, int64_t *samples, GPR_ASSERT(grpc_bdp_estimator_add_incoming_bytes(estimator, samples[i]) == false); } + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(1, GPR_TIMESPAN))); grpc_bdp_estimator_complete_ping(estimator); } @@ -123,24 +126,25 @@ static void test_get_estimate_random_values(size_t n) { gpr_log(GPR_INFO, "test_get_estimate_random_values(%" PRIdPTR ")", n); grpc_bdp_estimator est; grpc_bdp_estimator_init(&est, "test"); - int min = INT_MAX; - int max = 65535; // Windows rand() has limited range, make sure the ASSERT - // passes + const int kMaxSample = 65535; + int min = kMaxSample; + int max = 0; for (size_t i = 0; i < n; i++) { - int sample = rand(); + int sample = rand() % (kMaxSample + 1); if (sample < min) min = sample; if (sample > max) max = sample; add_sample(&est, sample); if (i >= 3) { gpr_log(GPR_DEBUG, "est:%" PRId64 " min:%d max:%d", get_estimate(&est), min, max); - GPR_ASSERT(get_estimate(&est) <= 2 * next_pow_2(max)); + GPR_ASSERT(get_estimate(&est) <= GPR_MAX(65536, 2 * next_pow_2(max))); } } } int main(int argc, char **argv) { grpc_test_init(argc, argv); + grpc_init(); test_noop(); test_get_estimate_no_samples(); test_get_estimate_1_sample(); @@ -149,5 +153,6 @@ int main(int argc, char **argv) { for (size_t i = 3; i < 1000; i = i * 3 / 2) { test_get_estimate_random_values(i); } + grpc_shutdown(); return 0; } diff --git a/test/core/transport/connectivity_state_test.c b/test/core/transport/connectivity_state_test.c index 8314a5f6190a4e3ef1babaaa929a621a0e5dbf33..96db59ba2df8221da0cfdcff10868ea1955898c9 100644 --- a/test/core/transport/connectivity_state_test.c +++ b/test/core/transport/connectivity_state_test.c @@ -151,7 +151,7 @@ static void test_subscribe_with_failure_then_destroy(void) { int main(int argc, char **argv) { grpc_test_init(argc, argv); - grpc_connectivity_state_trace = 1; + grpc_connectivity_state_trace.value = 1; test_connectivity_state_name(); test_check(); test_subscribe_then_unsubscribe(); diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c index 254c3a6b61387915441bfb9a6d7f716a79bfa3cc..6ef0acfc29bdbd0ba6d8e1ad71ec950fd0d0d7da 100644 --- a/test/core/util/port_server_client.c +++ b/test/core/util/port_server_client.c @@ -58,9 +58,8 @@ typedef struct freereq { static void destroy_pops_and_shutdown(grpc_exec_ctx *exec_ctx, void *p, grpc_error *error) { grpc_pollset *pollset = grpc_polling_entity_pollset(p); - grpc_pollset_destroy(pollset); + grpc_pollset_destroy(exec_ctx, pollset); gpr_free(pollset); - grpc_shutdown(); } static void freed_port_from_server(grpc_exec_ctx *exec_ctx, void *arg, @@ -122,12 +121,13 @@ void grpc_free_port_using_server(int port) { gpr_mu_unlock(pr.mu); grpc_httpcli_context_destroy(&exec_ctx, &context); - grpc_exec_ctx_finish(&exec_ctx); grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), shutdown_closure); grpc_exec_ctx_finish(&exec_ctx); gpr_free(path); grpc_http_response_destroy(&rsp); + + grpc_shutdown(); } typedef struct portreq { @@ -239,7 +239,6 @@ int grpc_pick_port_using_server(void) { grpc_closure_create(got_port_from_server, &pr, grpc_schedule_on_exec_ctx), &pr.response); grpc_resource_quota_unref_internal(&exec_ctx, resource_quota); - grpc_exec_ctx_finish(&exec_ctx); gpr_mu_lock(pr.mu); while (pr.port == -1) { grpc_pollset_worker *worker = NULL; @@ -258,6 +257,7 @@ int grpc_pick_port_using_server(void) { grpc_pollset_shutdown(&exec_ctx, grpc_polling_entity_pollset(&pr.pops), shutdown_closure); grpc_exec_ctx_finish(&exec_ctx); + grpc_shutdown(); return pr.port; } diff --git a/test/core/util/test_tcp_server.c b/test/core/util/test_tcp_server.c index 496e579bc396a00f6c2c4d6f15186e208953a3af..190869800921e423869285c0052c85a338316260 100644 --- a/test/core/util/test_tcp_server.c +++ b/test/core/util/test_tcp_server.c @@ -106,6 +106,10 @@ void test_tcp_server_poll(test_tcp_server *server, int seconds) { } static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {} +static void finish_pollset(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + grpc_pollset_destroy(exec_ctx, arg); +} void test_tcp_server_destroy(test_tcp_server *server) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; @@ -120,9 +124,10 @@ void test_tcp_server_destroy(test_tcp_server *server) { gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), shutdown_deadline) < 0) { test_tcp_server_poll(server, 1); } - grpc_pollset_shutdown(&exec_ctx, server->pollset, &do_nothing_cb); + grpc_pollset_shutdown(&exec_ctx, server->pollset, + grpc_closure_create(finish_pollset, server->pollset, + grpc_schedule_on_exec_ctx)); grpc_exec_ctx_finish(&exec_ctx); - grpc_pollset_destroy(server->pollset); gpr_free(server->pollset); grpc_shutdown(); } diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c index 58ac59711be1e3b79852de4e2c49890024707a5e..69386a0718110f404dab786cb2cc84d5081ea61b 100644 --- a/test/core/util/trickle_endpoint.c +++ b/test/core/util/trickle_endpoint.c @@ -44,6 +44,8 @@ #include <grpc/support/useful.h> #include "src/core/lib/slice/slice_internal.h" +#define WRITE_BUFFER_SIZE (2 * 1024 * 1024) + typedef struct { grpc_endpoint base; double bytes_per_second; @@ -55,6 +57,7 @@ typedef struct { grpc_slice_buffer writing_buffer; grpc_error *error; bool writing; + grpc_closure *write_cb; } trickle_endpoint; static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, @@ -63,10 +66,20 @@ static void te_read(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_endpoint_read(exec_ctx, te->wrapped, slices, cb); } +static void maybe_call_write_cb_locked(grpc_exec_ctx *exec_ctx, + trickle_endpoint *te) { + if (te->write_cb != NULL && (te->error != GRPC_ERROR_NONE || + te->write_buffer.length <= WRITE_BUFFER_SIZE)) { + grpc_closure_sched(exec_ctx, te->write_cb, GRPC_ERROR_REF(te->error)); + te->write_cb = NULL; + } +} + static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer *slices, grpc_closure *cb) { trickle_endpoint *te = (trickle_endpoint *)ep; gpr_mu_lock(&te->mu); + GPR_ASSERT(te->write_cb == NULL); if (te->write_buffer.length == 0) { te->last_write = gpr_now(GPR_CLOCK_MONOTONIC); } @@ -74,7 +87,8 @@ static void te_write(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, grpc_slice_buffer_add(&te->write_buffer, grpc_slice_copy(slices->slices[i])); } - grpc_closure_sched(exec_ctx, cb, GRPC_ERROR_REF(te->error)); + te->write_cb = cb; + maybe_call_write_cb_locked(exec_ctx, te); gpr_mu_unlock(&te->mu); } @@ -102,6 +116,7 @@ static void te_shutdown(grpc_exec_ctx *exec_ctx, grpc_endpoint *ep, if (te->error == GRPC_ERROR_NONE) { te->error = GRPC_ERROR_REF(why); } + maybe_call_write_cb_locked(exec_ctx, te); gpr_mu_unlock(&te->mu); grpc_endpoint_shutdown(exec_ctx, te->wrapped, why); } @@ -157,6 +172,7 @@ grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, te->base.vtable = &vtable; te->wrapped = wrap; te->bytes_per_second = bytes_per_second; + te->write_cb = NULL; gpr_mu_init(&te->mu); grpc_slice_buffer_init(&te->write_buffer); grpc_slice_buffer_init(&te->writing_buffer); @@ -187,9 +203,18 @@ size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx, grpc_endpoint_write( exec_ctx, te->wrapped, &te->writing_buffer, grpc_closure_create(te_finish_write, te, grpc_schedule_on_exec_ctx)); + maybe_call_write_cb_locked(exec_ctx, te); } } size_t backlog = te->write_buffer.length; gpr_mu_unlock(&te->mu); return backlog; } + +size_t grpc_trickle_get_backlog(grpc_endpoint *ep) { + trickle_endpoint *te = (trickle_endpoint *)ep; + gpr_mu_lock(&te->mu); + size_t backlog = te->write_buffer.length; + gpr_mu_unlock(&te->mu); + return backlog; +} diff --git a/test/core/util/trickle_endpoint.h b/test/core/util/trickle_endpoint.h index 7e8d9d91e33f2cf0b713f6e44a5274cc0594874c..e513774eb4aac772e1076b003b2a6390a3c061bb 100644 --- a/test/core/util/trickle_endpoint.h +++ b/test/core/util/trickle_endpoint.h @@ -43,4 +43,6 @@ grpc_endpoint *grpc_trickle_endpoint_create(grpc_endpoint *wrap, size_t grpc_trickle_endpoint_trickle(grpc_exec_ctx *exec_ctx, grpc_endpoint *endpoint); +size_t grpc_trickle_get_backlog(grpc_endpoint *endpoint); + #endif diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 25c221bb2b09600cb23259b416f09518fabb9f31..2c9f5e38e6c8a166a2a74b465348e393a6698422 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -115,6 +115,10 @@ class GenericEnd2endTest : public ::testing::Test { void client_fail(int i) { verify_ok(&cli_cq_, i, false); } void SendRpc(int num_rpcs) { + SendRpc(num_rpcs, false, gpr_inf_future(GPR_CLOCK_MONOTONIC)); + } + + void SendRpc(int num_rpcs, bool check_deadline, gpr_timespec deadline) { const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo"); for (int i = 0; i < num_rpcs; i++) { EchoRequest send_request; @@ -129,6 +133,11 @@ class GenericEnd2endTest : public ::testing::Test { // The string needs to be long enough to test heap-based slice. send_request.set_message("Hello world. Hello world. Hello world."); + + if (check_deadline) { + cli_ctx.set_deadline(deadline); + } + std::unique_ptr<GenericClientAsyncReaderWriter> call = generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1)); client_ok(1); @@ -147,6 +156,12 @@ class GenericEnd2endTest : public ::testing::Test { verify_ok(srv_cq_.get(), 4, true); EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length())); EXPECT_EQ(kMethodName, srv_ctx.method()); + + if (check_deadline) { + EXPECT_TRUE(gpr_time_similar(deadline, srv_ctx.raw_deadline(), + gpr_time_from_millis(100, GPR_TIMESPAN))); + } + ByteBuffer recv_buffer; stream.Read(&recv_buffer, tag(5)); server_ok(5); @@ -262,6 +277,12 @@ TEST_F(GenericEnd2endTest, SimpleBidiStreaming) { EXPECT_TRUE(recv_status.ok()); } +TEST_F(GenericEnd2endTest, Deadline) { + ResetStub(); + SendRpc(1, true, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_seconds(10, GPR_TIMESPAN))); +} + } // namespace } // namespace testing } // namespace grpc diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD index cae3fa1a1461bcb30837cdcf7fb9a81b8e0f5ebc..208ac6d794bd1f9ea2a82157a9c35d37e85a2a19 100644 --- a/test/cpp/microbenchmarks/BUILD +++ b/test/cpp/microbenchmarks/BUILD @@ -92,7 +92,7 @@ cc_test( cc_test( name = "bm_fullstack_trickle", srcs = ["bm_fullstack_trickle.cc"], - deps = [":helpers"], + deps = [":helpers", "//external:gflags"], ) cc_test( diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index c91219e98c8ce3467f9e7d5429f7201feb8843f5..67e7c025351dfd0c9749e4cf65c5333fc3518337 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -563,7 +563,8 @@ static void BM_IsolatedFilter(benchmark::State &state) { } grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; - size_t channel_size = grpc_channel_stack_size(&filters[0], filters.size()); + size_t channel_size = grpc_channel_stack_size( + filters.size() == 0 ? NULL : &filters[0], filters.size()); grpc_channel_stack *channel_stack = static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size)); GPR_ASSERT(GRPC_LOG_IF_ERROR( diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc index 9d7f65d2923001d923293041e1007d0ddedf91f2..0d267da72377e1998bdf22d57335cce6f2bc66e5 100644 --- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc +++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc @@ -67,7 +67,9 @@ static void pollset_init(grpc_pollset* ps, gpr_mu** mu) { *mu = &ps->mu; } -static void pollset_destroy(grpc_pollset* ps) { gpr_mu_destroy(&ps->mu); } +static void pollset_destroy(grpc_exec_ctx* exec_ctx, grpc_pollset* ps) { + gpr_mu_destroy(&ps->mu); +} static grpc_error* pollset_kick(grpc_pollset* p, grpc_pollset_worker* worker) { return GRPC_ERROR_NONE; diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc index 47705d3031895c967a87d31c6d80e8ad41734b5b..01ff39121e80a819cd001f73a9d8fcf23da96f16 100644 --- a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc +++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc @@ -105,6 +105,17 @@ static void BM_PumpStreamClientToServer(benchmark::State& state) { GPR_ASSERT(need_tags & (1 << i)); need_tags &= ~(1 << i); } + response_rw.Finish(Status::OK, tag(0)); + Status final_status; + request_rw->Finish(&final_status, tag(1)); + need_tags = (1 << 0) | (1 << 1); + while (need_tags) { + GPR_ASSERT(fixture->cq()->Next(&t, &ok)); + int i = (int)(intptr_t)t; + GPR_ASSERT(need_tags & (1 << i)); + need_tags &= ~(1 << i); + } + GPR_ASSERT(final_status.ok()); } fixture->Finish(state); fixture.reset(); diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc index a5cfeb4f955de18ef97991a93b356d6ae4d2d4fe..6b9fa8b38da83fbc31ca70b69bbf104df6bc97af 100644 --- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc +++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc @@ -34,6 +34,8 @@ /* Benchmark gRPC end2end in various configurations */ #include <benchmark/benchmark.h> +#include <gflags/gflags.h> +#include <fstream> #include "src/core/lib/profiling/timers.h" #include "src/cpp/client/create_channel_internal.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" @@ -45,16 +47,58 @@ extern "C" { #include "test/core/util/trickle_endpoint.h" } +DEFINE_bool(log, false, "Log state to CSV files"); +DEFINE_int32( + warmup_megabytes, 1, + "Number of megabytes to pump before collecting flow control stats"); +DEFINE_int32( + warmup_iterations, 100, + "Number of iterations to run before collecting flow control stats"); +DEFINE_int32(warmup_max_time_seconds, 10, + "Maximum number of seconds to run warmup loop"); + namespace grpc { namespace testing { static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); } +template <class A0> +static void write_csv(std::ostream* out, A0&& a0) { + if (!out) return; + (*out) << a0 << "\n"; +} + +template <class A0, class... Arg> +static void write_csv(std::ostream* out, A0&& a0, Arg&&... arg) { + if (!out) return; + (*out) << a0 << ","; + write_csv(out, std::forward<Arg>(arg)...); +} + class TrickledCHTTP2 : public EndpointPairFixture { public: - TrickledCHTTP2(Service* service, size_t megabits_per_second) - : EndpointPairFixture(service, MakeEndpoints(megabits_per_second), - FixtureConfiguration()) {} + TrickledCHTTP2(Service* service, bool streaming, size_t req_size, + size_t resp_size, size_t kilobits_per_second) + : EndpointPairFixture(service, MakeEndpoints(kilobits_per_second), + FixtureConfiguration()) { + if (FLAGS_log) { + std::ostringstream fn; + fn << "trickle." << (streaming ? "streaming" : "unary") << "." << req_size + << "." << resp_size << "." << kilobits_per_second << ".csv"; + log_.reset(new std::ofstream(fn.str().c_str())); + write_csv(log_.get(), "t", "iteration", "client_backlog", + "server_backlog", "client_t_stall", "client_s_stall", + "server_t_stall", "server_s_stall", "client_t_outgoing", + "server_t_outgoing", "client_t_incoming", "server_t_incoming", + "client_s_outgoing_delta", "server_s_outgoing_delta", + "client_s_incoming_delta", "server_s_incoming_delta", + "client_s_announce_window", "server_s_announce_window", + "client_peer_iws", "client_local_iws", "client_sent_iws", + "client_acked_iws", "server_peer_iws", "server_local_iws", + "server_sent_iws", "server_acked_iws", "client_queued_bytes", + "server_queued_bytes"); + } + } void AddToLabel(std::ostream& out, benchmark::State& state) { out << " writes/iter:" @@ -75,7 +119,58 @@ class TrickledCHTTP2 : public EndpointPairFixture { (double)state.iterations()); } - void Step() { + void Log(int64_t iteration) { + auto now = gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), start_); + grpc_chttp2_transport* client = + reinterpret_cast<grpc_chttp2_transport*>(client_transport_); + grpc_chttp2_transport* server = + reinterpret_cast<grpc_chttp2_transport*>(server_transport_); + grpc_chttp2_stream* client_stream = + client->stream_map.count == 1 + ? static_cast<grpc_chttp2_stream*>(client->stream_map.values[0]) + : nullptr; + grpc_chttp2_stream* server_stream = + server->stream_map.count == 1 + ? static_cast<grpc_chttp2_stream*>(server->stream_map.values[0]) + : nullptr; + write_csv( + log_.get(), static_cast<double>(now.tv_sec) + + 1e-9 * static_cast<double>(now.tv_nsec), + iteration, grpc_trickle_get_backlog(endpoint_pair_.client), + grpc_trickle_get_backlog(endpoint_pair_.server), + client->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != nullptr, + client->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != nullptr, + server->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != nullptr, + server->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != nullptr, + client->outgoing_window, server->outgoing_window, + client->incoming_window, server->incoming_window, + client_stream ? client_stream->outgoing_window_delta : -1, + server_stream ? server_stream->outgoing_window_delta : -1, + client_stream ? client_stream->incoming_window_delta : -1, + server_stream ? server_stream->incoming_window_delta : -1, + client_stream ? client_stream->announce_window : -1, + server_stream ? server_stream->announce_window : -1, + client->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + client->settings[GRPC_LOCAL_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + client->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + client->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + server->settings[GRPC_PEER_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + server->settings[GRPC_LOCAL_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + server->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + server->settings[GRPC_ACKED_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], + client_stream ? client_stream->flow_controlled_buffer.length : 0, + server_stream ? server_stream->flow_controlled_buffer.length : 0); + } + + void Step(bool update_stats) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; size_t client_backlog = grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.client); @@ -83,10 +178,12 @@ class TrickledCHTTP2 : public EndpointPairFixture { grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.server); grpc_exec_ctx_finish(&exec_ctx); - UpdateStats((grpc_chttp2_transport*)client_transport_, &client_stats_, - client_backlog); - UpdateStats((grpc_chttp2_transport*)server_transport_, &server_stats_, - server_backlog); + if (update_stats) { + UpdateStats((grpc_chttp2_transport*)client_transport_, &client_stats_, + client_backlog); + UpdateStats((grpc_chttp2_transport*)server_transport_, &server_stats_, + server_backlog); + } } private: @@ -97,6 +194,8 @@ class TrickledCHTTP2 : public EndpointPairFixture { }; Stats client_stats_; Stats server_stats_; + std::unique_ptr<std::ofstream> log_; + gpr_timespec start_ = gpr_now(GPR_CLOCK_MONOTONIC); grpc_endpoint_pair MakeEndpoints(size_t kilobits) { grpc_endpoint_pair p; @@ -123,13 +222,15 @@ class TrickledCHTTP2 : public EndpointPairFixture { // force library initialization auto& force_library_initialization = Library::get(); -static void TrickleCQNext(TrickledCHTTP2* fixture, void** t, bool* ok) { +static void TrickleCQNext(TrickledCHTTP2* fixture, void** t, bool* ok, + int64_t iteration) { while (true) { + fixture->Log(iteration); switch (fixture->cq()->AsyncNext( t, ok, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_micros(100, GPR_TIMESPAN)))) { case CompletionQueue::TIMEOUT: - fixture->Step(); + fixture->Step(iteration != -1); break; case CompletionQueue::SHUTDOWN: GPR_ASSERT(false); @@ -142,8 +243,9 @@ static void TrickleCQNext(TrickledCHTTP2* fixture, void** t, bool* ok) { static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) { EchoTestService::AsyncService service; - std::unique_ptr<TrickledCHTTP2> fixture( - new TrickledCHTTP2(&service, state.range(1))); + std::unique_ptr<TrickledCHTTP2> fixture(new TrickledCHTTP2( + &service, true, state.range(0) /* req_size */, + state.range(0) /* resp_size */, state.range(1) /* bw in kbit/s */)); { EchoResponse send_response; EchoResponse recv_response; @@ -163,18 +265,19 @@ static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) { void* t; bool ok; while (need_tags) { - TrickleCQNext(fixture.get(), &t, &ok); + TrickleCQNext(fixture.get(), &t, &ok, -1); GPR_ASSERT(ok); int i = (int)(intptr_t)t; GPR_ASSERT(need_tags & (1 << i)); need_tags &= ~(1 << i); } request_rw->Read(&recv_response, tag(0)); - while (state.KeepRunning()) { + auto inner_loop = [&](bool in_warmup) { GPR_TIMER_SCOPE("BenchmarkCycle", 0); response_rw.Write(send_response, tag(1)); while (true) { - TrickleCQNext(fixture.get(), &t, &ok); + TrickleCQNext(fixture.get(), &t, &ok, + in_warmup ? -1 : state.iterations()); if (t == tag(0)) { request_rw->Read(&recv_response, tag(0)); } else if (t == tag(1)) { @@ -183,11 +286,26 @@ static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) { GPR_ASSERT(false); } } + }; + gpr_timespec warmup_start = gpr_now(GPR_CLOCK_MONOTONIC); + for (int i = 0; + i < GPR_MAX(FLAGS_warmup_iterations, FLAGS_warmup_megabytes * 1024 * + 1024 / (14 + state.range(0))); + i++) { + inner_loop(true); + if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), warmup_start), + gpr_time_from_seconds(FLAGS_warmup_max_time_seconds, + GPR_TIMESPAN)) > 0) { + break; + } + } + while (state.KeepRunning()) { + inner_loop(false); } response_rw.Finish(Status::OK, tag(1)); need_tags = (1 << 0) | (1 << 1); while (need_tags) { - TrickleCQNext(fixture.get(), &t, &ok); + TrickleCQNext(fixture.get(), &t, &ok, -1); int i = (int)(intptr_t)t; GPR_ASSERT(need_tags & (1 << i)); need_tags &= ~(1 << i); @@ -198,23 +316,126 @@ static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) { state.SetBytesProcessed(state.range(0) * state.iterations()); } -/******************************************************************************* - * CONFIGURATIONS - */ - -static void TrickleArgs(benchmark::internal::Benchmark* b) { +static void StreamingTrickleArgs(benchmark::internal::Benchmark* b) { for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) { - for (int j = 1; j <= 128 * 1024 * 1024; j *= 8) { + for (int j = 64; j <= 128 * 1024 * 1024; j *= 8) { double expected_time = static_cast<double>(14 + i) / (125.0 * static_cast<double>(j)); - if (expected_time > 0.01) continue; + if (expected_time > 2.0) continue; b->Args({i, j}); } } } +BENCHMARK(BM_PumpStreamServerToClient_Trickle)->Apply(StreamingTrickleArgs); + +static void BM_PumpUnbalancedUnary_Trickle(benchmark::State& state) { + EchoTestService::AsyncService service; + std::unique_ptr<TrickledCHTTP2> fixture(new TrickledCHTTP2( + &service, true, state.range(0) /* req_size */, + state.range(1) /* resp_size */, state.range(2) /* bw in kbit/s */)); + EchoRequest send_request; + EchoResponse send_response; + EchoResponse recv_response; + if (state.range(0) > 0) { + send_request.set_message(std::string(state.range(0), 'a')); + } + if (state.range(1) > 0) { + send_response.set_message(std::string(state.range(1), 'a')); + } + Status recv_status; + struct ServerEnv { + ServerContext ctx; + EchoRequest recv_request; + grpc::ServerAsyncResponseWriter<EchoResponse> response_writer; + ServerEnv() : response_writer(&ctx) {} + }; + uint8_t server_env_buffer[2 * sizeof(ServerEnv)]; + ServerEnv* server_env[2] = { + reinterpret_cast<ServerEnv*>(server_env_buffer), + reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))}; + new (server_env[0]) ServerEnv; + new (server_env[1]) ServerEnv; + service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request, + &server_env[0]->response_writer, fixture->cq(), + fixture->cq(), tag(0)); + service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request, + &server_env[1]->response_writer, fixture->cq(), + fixture->cq(), tag(1)); + std::unique_ptr<EchoTestService::Stub> stub( + EchoTestService::NewStub(fixture->channel())); + auto inner_loop = [&](bool in_warmup) { + GPR_TIMER_SCOPE("BenchmarkCycle", 0); + recv_response.Clear(); + ClientContext cli_ctx; + std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader( + stub->AsyncEcho(&cli_ctx, send_request, fixture->cq())); + void* t; + bool ok; + TrickleCQNext(fixture.get(), &t, &ok, state.iterations()); + GPR_ASSERT(ok); + GPR_ASSERT(t == tag(0) || t == tag(1)); + intptr_t slot = reinterpret_cast<intptr_t>(t); + ServerEnv* senv = server_env[slot]; + senv->response_writer.Finish(send_response, Status::OK, tag(3)); + response_reader->Finish(&recv_response, &recv_status, tag(4)); + for (int i = (1 << 3) | (1 << 4); i != 0;) { + TrickleCQNext(fixture.get(), &t, &ok, state.iterations()); + GPR_ASSERT(ok); + int tagnum = (int)reinterpret_cast<intptr_t>(t); + GPR_ASSERT(i & (1 << tagnum)); + i -= 1 << tagnum; + } + GPR_ASSERT(recv_status.ok()); + + senv->~ServerEnv(); + senv = new (senv) ServerEnv(); + service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer, + fixture->cq(), fixture->cq(), tag(slot)); + }; + gpr_timespec warmup_start = gpr_now(GPR_CLOCK_MONOTONIC); + for (int i = 0; + i < GPR_MAX(FLAGS_warmup_iterations, FLAGS_warmup_megabytes * 1024 * + 1024 / (14 + state.range(0))); + i++) { + inner_loop(true); + if (gpr_time_cmp(gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), warmup_start), + gpr_time_from_seconds(FLAGS_warmup_max_time_seconds, + GPR_TIMESPAN)) > 0) { + break; + } + } + while (state.KeepRunning()) { + inner_loop(false); + } + fixture->Finish(state); + fixture.reset(); + server_env[0]->~ServerEnv(); + server_env[1]->~ServerEnv(); + state.SetBytesProcessed(state.range(0) * state.iterations() + + state.range(1) * state.iterations()); +} -BENCHMARK(BM_PumpStreamServerToClient_Trickle)->Apply(TrickleArgs); +static void UnaryTrickleArgs(benchmark::internal::Benchmark* b) { + const int cli_1024k = 1024 * 1024; + const int cli_32M = 32 * 1024 * 1024; + const int svr_256k = 256 * 1024; + const int svr_4M = 4 * 1024 * 1024; + const int svr_64M = 64 * 1024 * 1024; + for (int bw = 64; bw <= 128 * 1024 * 1024; bw *= 16) { + b->Args({bw, cli_1024k, svr_256k}); + b->Args({bw, cli_1024k, svr_4M}); + b->Args({bw, cli_1024k, svr_64M}); + b->Args({bw, cli_32M, svr_256k}); + b->Args({bw, cli_32M, svr_4M}); + b->Args({bw, cli_32M, svr_64M}); + } +} +BENCHMARK(BM_PumpUnbalancedUnary_Trickle)->Apply(UnaryTrickleArgs); } } -BENCHMARK_MAIN(); +int main(int argc, char** argv) { + ::benchmark::Initialize(&argc, argv); + ::google::ParseCommandLineFlags(&argc, &argv, false); + ::benchmark::RunSpecifiedBenchmarks(); +} diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc index 0f3d3cef66a9e9c4fae30305e078d6a4dfe9b373..f5e8d13881fee1bbf59e25a267376d0c6342d123 100644 --- a/test/cpp/microbenchmarks/bm_pollset.cc +++ b/test/cpp/microbenchmarks/bm_pollset.cc @@ -59,7 +59,7 @@ extern "C" { auto& force_library_initialization = Library::get(); static void shutdown_ps(grpc_exec_ctx* exec_ctx, void* ps, grpc_error* error) { - grpc_pollset_destroy(static_cast<grpc_pollset*>(ps)); + grpc_pollset_destroy(exec_ctx, static_cast<grpc_pollset*>(ps)); } static void BM_CreateDestroyPollset(benchmark::State& state) { @@ -136,8 +136,7 @@ static void BM_PollEmptyPollset(benchmark::State& state) { gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC); gpr_mu_lock(mu); while (state.KeepRunning()) { - grpc_pollset_worker* worker; - GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, &worker, now, deadline)); + GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, NULL, now, deadline)); } grpc_closure shutdown_ps_closure; grpc_closure_init(&shutdown_ps_closure, shutdown_ps, ps, @@ -150,6 +149,34 @@ static void BM_PollEmptyPollset(benchmark::State& state) { } BENCHMARK(BM_PollEmptyPollset); +static void BM_PollAddFd(benchmark::State& state) { + TrackCounters track_counters; + size_t ps_sz = grpc_pollset_size(); + grpc_pollset* ps = static_cast<grpc_pollset*>(gpr_zalloc(ps_sz)); + gpr_mu* mu; + grpc_pollset_init(ps, &mu); + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_wakeup_fd wakeup_fd; + GPR_ASSERT( + GRPC_LOG_IF_ERROR("wakeup_fd_init", grpc_wakeup_fd_init(&wakeup_fd))); + grpc_fd* fd = grpc_fd_create(wakeup_fd.read_fd, "xxx"); + while (state.KeepRunning()) { + grpc_pollset_add_fd(&exec_ctx, ps, fd); + grpc_exec_ctx_flush(&exec_ctx); + } + grpc_fd_orphan(&exec_ctx, fd, NULL, NULL, "xxx"); + grpc_closure shutdown_ps_closure; + grpc_closure_init(&shutdown_ps_closure, shutdown_ps, ps, + grpc_schedule_on_exec_ctx); + gpr_mu_lock(mu); + grpc_pollset_shutdown(&exec_ctx, ps, &shutdown_ps_closure); + gpr_mu_unlock(mu); + grpc_exec_ctx_finish(&exec_ctx); + gpr_free(ps); + track_counters.Finish(state); +} +BENCHMARK(BM_PollAddFd); + class Closure : public grpc_closure { public: virtual ~Closure() {} @@ -233,8 +260,7 @@ static void BM_SingleThreadPollOneFd(benchmark::State& state) { grpc_fd_notify_on_read(&exec_ctx, wakeup, continue_closure); gpr_mu_lock(mu); while (!done) { - grpc_pollset_worker* worker; - GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, &worker, now, deadline)); + GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, NULL, now, deadline)); } grpc_fd_orphan(&exec_ctx, wakeup, NULL, NULL, "done"); wakeup_fd.read_fd = 0; diff --git a/test/cpp/microbenchmarks/helpers.cc b/test/cpp/microbenchmarks/helpers.cc index 6550742453a77674ec0fe74cb5c1049573846b5c..73ab9e4a1ac4f95870721defc8ce0eae4c749177 100644 --- a/test/cpp/microbenchmarks/helpers.cc +++ b/test/cpp/microbenchmarks/helpers.cc @@ -36,11 +36,11 @@ void TrackCounters::Finish(benchmark::State &state) { std::ostringstream out; AddToLabel(out, state); - auto label = out.str(); + std::string label = out.str(); if (label.length() && label[0] == ' ') { label = label.substr(1); } - state.SetLabel(label); + state.SetLabel(label.c_str()); } void TrackCounters::AddToLabel(std::ostream &out, benchmark::State &state) { diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc index 7a914c15474d6b6bef0e6c71869518648932df64..12d8268330c26de906be7b5c3882e0caa5c470d3 100644 --- a/test/cpp/performance/writes_per_rpc_test.cc +++ b/test/cpp/performance/writes_per_rpc_test.cc @@ -254,8 +254,8 @@ TEST(WritesPerRpcTest, UnaryPingPong) { EXPECT_LT(UnaryPingPong(0, 0), 2.05); EXPECT_LT(UnaryPingPong(1, 0), 2.05); EXPECT_LT(UnaryPingPong(0, 1), 2.05); - EXPECT_LT(UnaryPingPong(4096, 0), 2.2); - EXPECT_LT(UnaryPingPong(0, 4096), 2.2); + EXPECT_LT(UnaryPingPong(4096, 0), 2.5); + EXPECT_LT(UnaryPingPong(0, 4096), 2.5); } } // namespace testing diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 01856f714a5816f1a7ca7845739e8149940d151a..82c3356f021cb06bc11720a466621b5f16797c88 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -238,39 +238,27 @@ class AsyncClient : public ClientImpl<StubType, RequestType> { void* got_tag; bool ok; - switch (cli_cqs_[thread_idx]->AsyncNext( - &got_tag, &ok, - std::chrono::system_clock::now() + std::chrono::milliseconds(10))) { - case CompletionQueue::GOT_EVENT: { - // Got a regular event, so process it - ClientRpcContext* ctx = ClientRpcContext::detag(got_tag); - // Proceed while holding a lock to make sure that - // this thread isn't supposed to shut down - std::lock_guard<std::mutex> l(shutdown_state_[thread_idx]->mutex); - if (shutdown_state_[thread_idx]->shutdown) { - delete ctx; - return true; - } else if (!ctx->RunNextState(ok, entry)) { - // The RPC and callback are done, so clone the ctx - // and kickstart the new one - ctx->StartNewClone(cli_cqs_[thread_idx].get()); - // delete the old version - delete ctx; - } + if (cli_cqs_[thread_idx]->Next(&got_tag, &ok)) { + // Got a regular event, so process it + ClientRpcContext* ctx = ClientRpcContext::detag(got_tag); + // Proceed while holding a lock to make sure that + // this thread isn't supposed to shut down + std::lock_guard<std::mutex> l(shutdown_state_[thread_idx]->mutex); + if (shutdown_state_[thread_idx]->shutdown) { + delete ctx; return true; + } else if (!ctx->RunNextState(ok, entry)) { + // The RPC and callback are done, so clone the ctx + // and kickstart the new one + ctx->StartNewClone(cli_cqs_[thread_idx].get()); + // delete the old version + delete ctx; } - case CompletionQueue::TIMEOUT: { - std::lock_guard<std::mutex> l(shutdown_state_[thread_idx]->mutex); - if (shutdown_state_[thread_idx]->shutdown) { - return true; - } - return true; - } - case CompletionQueue::SHUTDOWN: // queue is shutting down, so we must be - // done - return true; + return true; + } else { + // queue is shutting down, so we must be done + return true; } - GPR_UNREACHABLE_CODE(return true); } std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_; diff --git a/tools/distrib/python/grpcio_tools/protoc_lib_deps.py b/tools/distrib/python/grpcio_tools/protoc_lib_deps.py index c2aa6198b3d7c442548f2f1c4fa9dd5c18a76e63..8a251f876ab9a609023713afef8ae494d016f501 100644 --- a/tools/distrib/python/grpcio_tools/protoc_lib_deps.py +++ b/tools/distrib/python/grpcio_tools/protoc_lib_deps.py @@ -29,8 +29,8 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # AUTO-GENERATED BY make_grpcio_tools.py! -CC_FILES=['google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/php/php_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/well_known_types_embed.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/javanano/javanano_primitive_field.cc', 'google/protobuf/compiler/javanano/javanano_message_field.cc', 'google/protobuf/compiler/javanano/javanano_message.cc', 'google/protobuf/compiler/javanano/javanano_map_field.cc', 'google/protobuf/compiler/javanano/javanano_helpers.cc', 'google/protobuf/compiler/javanano/javanano_generator.cc', 'google/protobuf/compiler/javanano/javanano_file.cc', 'google/protobuf/compiler/javanano/javanano_field.cc', 'google/protobuf/compiler/javanano/javanano_extension.cc', 'google/protobuf/compiler/javanano/javanano_enum_field.cc', 'google/protobuf/compiler/javanano/javanano_enum.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_lazy_message_field_lite.cc', 'google/protobuf/compiler/java/java_lazy_message_field.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension_lite.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/stubs/mathlimits.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/once.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/stubs/atomicops_internals_x86_msvc.cc', 'google/protobuf/stubs/atomicops_internals_x86_gcc.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc', 'google/protobuf/compiler/js/embed.cc'] -PROTO_FILES=['google/protobuf/wrappers.proto', 'google/protobuf/type.proto', 'google/protobuf/timestamp.proto', 'google/protobuf/struct.proto', 'google/protobuf/source_context.proto', 'google/protobuf/field_mask.proto', 'google/protobuf/empty.proto', 'google/protobuf/duration.proto', 'google/protobuf/descriptor.proto', 'google/protobuf/compiler/plugin.proto', 'google/protobuf/api.proto', 'google/protobuf/any.proto'] +CC_FILES=['google/protobuf/compiler/zip_writer.cc', 'google/protobuf/compiler/subprocess.cc', 'google/protobuf/compiler/ruby/ruby_generator.cc', 'google/protobuf/compiler/python/python_generator.cc', 'google/protobuf/compiler/profile.pb.cc', 'google/protobuf/compiler/plugin.pb.cc', 'google/protobuf/compiler/plugin.cc', 'google/protobuf/compiler/php/php_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_primitive_field.cc', 'google/protobuf/compiler/objectivec/objectivec_oneof.cc', 'google/protobuf/compiler/objectivec/objectivec_message_field.cc', 'google/protobuf/compiler/objectivec/objectivec_message.cc', 'google/protobuf/compiler/objectivec/objectivec_map_field.cc', 'google/protobuf/compiler/objectivec/objectivec_helpers.cc', 'google/protobuf/compiler/objectivec/objectivec_generator.cc', 'google/protobuf/compiler/objectivec/objectivec_file.cc', 'google/protobuf/compiler/objectivec/objectivec_field.cc', 'google/protobuf/compiler/objectivec/objectivec_extension.cc', 'google/protobuf/compiler/objectivec/objectivec_enum_field.cc', 'google/protobuf/compiler/objectivec/objectivec_enum.cc', 'google/protobuf/compiler/js/well_known_types_embed.cc', 'google/protobuf/compiler/js/js_generator.cc', 'google/protobuf/compiler/javanano/javanano_primitive_field.cc', 'google/protobuf/compiler/javanano/javanano_message_field.cc', 'google/protobuf/compiler/javanano/javanano_message.cc', 'google/protobuf/compiler/javanano/javanano_map_field.cc', 'google/protobuf/compiler/javanano/javanano_helpers.cc', 'google/protobuf/compiler/javanano/javanano_generator.cc', 'google/protobuf/compiler/javanano/javanano_file.cc', 'google/protobuf/compiler/javanano/javanano_field.cc', 'google/protobuf/compiler/javanano/javanano_extension.cc', 'google/protobuf/compiler/javanano/javanano_enum_field.cc', 'google/protobuf/compiler/javanano/javanano_enum.cc', 'google/protobuf/compiler/java/java_string_field_lite.cc', 'google/protobuf/compiler/java/java_string_field.cc', 'google/protobuf/compiler/java/java_shared_code_generator.cc', 'google/protobuf/compiler/java/java_service.cc', 'google/protobuf/compiler/java/java_primitive_field_lite.cc', 'google/protobuf/compiler/java/java_primitive_field.cc', 'google/protobuf/compiler/java/java_name_resolver.cc', 'google/protobuf/compiler/java/java_message_lite.cc', 'google/protobuf/compiler/java/java_message_field_lite.cc', 'google/protobuf/compiler/java/java_message_field.cc', 'google/protobuf/compiler/java/java_message_builder_lite.cc', 'google/protobuf/compiler/java/java_message_builder.cc', 'google/protobuf/compiler/java/java_message.cc', 'google/protobuf/compiler/java/java_map_field_lite.cc', 'google/protobuf/compiler/java/java_map_field.cc', 'google/protobuf/compiler/java/java_lazy_message_field_lite.cc', 'google/protobuf/compiler/java/java_lazy_message_field.cc', 'google/protobuf/compiler/java/java_helpers.cc', 'google/protobuf/compiler/java/java_generator_factory.cc', 'google/protobuf/compiler/java/java_generator.cc', 'google/protobuf/compiler/java/java_file.cc', 'google/protobuf/compiler/java/java_field.cc', 'google/protobuf/compiler/java/java_extension_lite.cc', 'google/protobuf/compiler/java/java_extension.cc', 'google/protobuf/compiler/java/java_enum_lite.cc', 'google/protobuf/compiler/java/java_enum_field_lite.cc', 'google/protobuf/compiler/java/java_enum_field.cc', 'google/protobuf/compiler/java/java_enum.cc', 'google/protobuf/compiler/java/java_doc_comment.cc', 'google/protobuf/compiler/java/java_context.cc', 'google/protobuf/compiler/csharp/csharp_wrapper_field.cc', 'google/protobuf/compiler/csharp/csharp_source_generator_base.cc', 'google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_message_field.cc', 'google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_reflection_class.cc', 'google/protobuf/compiler/csharp/csharp_primitive_field.cc', 'google/protobuf/compiler/csharp/csharp_message_field.cc', 'google/protobuf/compiler/csharp/csharp_message.cc', 'google/protobuf/compiler/csharp/csharp_map_field.cc', 'google/protobuf/compiler/csharp/csharp_helpers.cc', 'google/protobuf/compiler/csharp/csharp_generator.cc', 'google/protobuf/compiler/csharp/csharp_field_base.cc', 'google/protobuf/compiler/csharp/csharp_enum_field.cc', 'google/protobuf/compiler/csharp/csharp_enum.cc', 'google/protobuf/compiler/csharp/csharp_doc_comment.cc', 'google/protobuf/compiler/cpp/cpp_string_field.cc', 'google/protobuf/compiler/cpp/cpp_service.cc', 'google/protobuf/compiler/cpp/cpp_primitive_field.cc', 'google/protobuf/compiler/cpp/cpp_message_field.cc', 'google/protobuf/compiler/cpp/cpp_message.cc', 'google/protobuf/compiler/cpp/cpp_map_field.cc', 'google/protobuf/compiler/cpp/cpp_helpers.cc', 'google/protobuf/compiler/cpp/cpp_generator.cc', 'google/protobuf/compiler/cpp/cpp_file.cc', 'google/protobuf/compiler/cpp/cpp_field.cc', 'google/protobuf/compiler/cpp/cpp_extension.cc', 'google/protobuf/compiler/cpp/cpp_enum_field.cc', 'google/protobuf/compiler/cpp/cpp_enum.cc', 'google/protobuf/compiler/command_line_interface.cc', 'google/protobuf/compiler/code_generator.cc', 'google/protobuf/wrappers.pb.cc', 'google/protobuf/wire_format.cc', 'google/protobuf/util/type_resolver_util.cc', 'google/protobuf/util/time_util.cc', 'google/protobuf/util/message_differencer.cc', 'google/protobuf/util/json_util.cc', 'google/protobuf/util/internal/utility.cc', 'google/protobuf/util/internal/type_info_test_helper.cc', 'google/protobuf/util/internal/type_info.cc', 'google/protobuf/util/internal/protostream_objectwriter.cc', 'google/protobuf/util/internal/protostream_objectsource.cc', 'google/protobuf/util/internal/proto_writer.cc', 'google/protobuf/util/internal/object_writer.cc', 'google/protobuf/util/internal/json_stream_parser.cc', 'google/protobuf/util/internal/json_objectwriter.cc', 'google/protobuf/util/internal/json_escaping.cc', 'google/protobuf/util/internal/field_mask_utility.cc', 'google/protobuf/util/internal/error_listener.cc', 'google/protobuf/util/internal/default_value_objectwriter.cc', 'google/protobuf/util/internal/datapiece.cc', 'google/protobuf/util/field_mask_util.cc', 'google/protobuf/util/field_comparator.cc', 'google/protobuf/util/delimited_message_util.cc', 'google/protobuf/unknown_field_set.cc', 'google/protobuf/type.pb.cc', 'google/protobuf/timestamp.pb.cc', 'google/protobuf/text_format.cc', 'google/protobuf/stubs/substitute.cc', 'google/protobuf/stubs/mathlimits.cc', 'google/protobuf/struct.pb.cc', 'google/protobuf/source_context.pb.cc', 'google/protobuf/service.cc', 'google/protobuf/reflection_ops.cc', 'google/protobuf/message.cc', 'google/protobuf/map_field.cc', 'google/protobuf/io/zero_copy_stream_impl.cc', 'google/protobuf/io/tokenizer.cc', 'google/protobuf/io/strtod.cc', 'google/protobuf/io/printer.cc', 'google/protobuf/io/gzip_stream.cc', 'google/protobuf/generated_message_reflection.cc', 'google/protobuf/field_mask.pb.cc', 'google/protobuf/extension_set_heavy.cc', 'google/protobuf/empty.pb.cc', 'google/protobuf/dynamic_message.cc', 'google/protobuf/duration.pb.cc', 'google/protobuf/descriptor_database.cc', 'google/protobuf/descriptor.pb.cc', 'google/protobuf/descriptor.cc', 'google/protobuf/compiler/parser.cc', 'google/protobuf/compiler/importer.cc', 'google/protobuf/api.pb.cc', 'google/protobuf/any.pb.cc', 'google/protobuf/any.cc', 'google/protobuf/wire_format_lite.cc', 'google/protobuf/stubs/time.cc', 'google/protobuf/stubs/strutil.cc', 'google/protobuf/stubs/structurally_valid.cc', 'google/protobuf/stubs/stringprintf.cc', 'google/protobuf/stubs/stringpiece.cc', 'google/protobuf/stubs/statusor.cc', 'google/protobuf/stubs/status.cc', 'google/protobuf/stubs/once.cc', 'google/protobuf/stubs/int128.cc', 'google/protobuf/stubs/common.cc', 'google/protobuf/stubs/bytestream.cc', 'google/protobuf/stubs/atomicops_internals_x86_msvc.cc', 'google/protobuf/stubs/atomicops_internals_x86_gcc.cc', 'google/protobuf/repeated_field.cc', 'google/protobuf/message_lite.cc', 'google/protobuf/io/zero_copy_stream_impl_lite.cc', 'google/protobuf/io/zero_copy_stream.cc', 'google/protobuf/io/coded_stream.cc', 'google/protobuf/generated_message_util.cc', 'google/protobuf/extension_set.cc', 'google/protobuf/arenastring.cc', 'google/protobuf/arena.cc', 'google/protobuf/compiler/js/embed.cc'] +PROTO_FILES=['google/protobuf/wrappers.proto', 'google/protobuf/type.proto', 'google/protobuf/timestamp.proto', 'google/protobuf/struct.proto', 'google/protobuf/source_context.proto', 'google/protobuf/field_mask.proto', 'google/protobuf/empty.proto', 'google/protobuf/duration.proto', 'google/protobuf/descriptor.proto', 'google/protobuf/compiler/profile.proto', 'google/protobuf/compiler/plugin.proto', 'google/protobuf/api.proto', 'google/protobuf/any.proto'] CC_INCLUDE='third_party/protobuf/src' PROTO_INCLUDE='third_party/protobuf/src' diff --git a/tools/distrib/python/grpcio_tools/setup.py b/tools/distrib/python/grpcio_tools/setup.py index 211d442f1767462adf0f3c6d616812c2d3a83408..43b60b142f3f747450fd62059413d0726dd9d507 100644 --- a/tools/distrib/python/grpcio_tools/setup.py +++ b/tools/distrib/python/grpcio_tools/setup.py @@ -211,7 +211,7 @@ setuptools.setup( ext_modules=extension_modules(), packages=setuptools.find_packages('.'), install_requires=[ - 'protobuf>=3.2.0', + 'protobuf>=3.3.0', 'grpcio>={version}'.format(version=grpc_version.VERSION), ], package_data=package_data(), diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile similarity index 90% rename from tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile rename to tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile index c099f339aeee5607f02a0718a239690bcede2de2..0a62f1c2c0f8636092ebecd1143f6323e859cef1 100644 --- a/tools/dockerfile/stress_test/grpc_interop_stress_go/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2016, Google Inc. +# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -27,12 +27,10 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -FROM golang:latest - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client +FROM golang:1.7 +# Using login shell removes Go from path, so we add it. +RUN ln -s /usr/local/go/bin/go /usr/local/bin #==================== # Python dependencies @@ -49,8 +47,5 @@ RUN pip install pip --upgrade RUN pip install virtualenv RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 -# Using login shell removes Go from path, so we add it. -RUN ln -s /usr/local/go/bin/go /usr/local/bin - # Define the default command. CMD ["bash"] diff --git a/tools/gcp/stress_test/run_node.sh b/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile old mode 100755 new mode 100644 similarity index 73% rename from tools/gcp/stress_test/run_node.sh rename to tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile index 4a4da6fc8b8e3c750890604c55c09698548d65f9..abf38b817a5ab6ddb501190e1e13c8cc1f2076f5 --- a/tools/gcp/stress_test/run_node.sh +++ b/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile @@ -1,5 +1,4 @@ -#!/bin/bash -# Copyright 2015-2016, Google Inc. +# Copyright 2017, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -28,10 +27,25 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# This is a wrapper script that was created to help run_server.py and -# run_client.py to launch 'node js' stress clients and stress servers -source ~/.nvm/nvm.sh +FROM golang:1.8 -set -ex +# Using login shell removes Go from path, so we add it. +RUN ln -s /usr/local/go/bin/go /usr/local/bin -$@ +#==================== +# Python dependencies + +# Install dependencies + +RUN apt-get update && apt-get install -y \ + python-all-dev \ + python3-all-dev \ + python-pip + +# Install Python packages from PyPI +RUN pip install pip --upgrade +RUN pip install virtualenv +RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 + +# Define the default command. +CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile deleted file mode 100644 index 12d8d091848444787da1ad59c1103727a99a48d7..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_csharp/Dockerfile +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - -#================= -# C++ dependencies -RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -#================ -# C# dependencies - -# Update to a newer version of mono -RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF -RUN echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list -RUN echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list - -# Install dependencies -RUN apt-get update && apt-get -y dist-upgrade && apt-get install -y \ - mono-devel \ - ca-certificates-mono \ - nuget \ - && apt-get clean - -RUN nuget update -self - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_csharp/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_csharp/build_interop_stress.sh deleted file mode 100755 index 345196894ef6a71e888a3fea739af70548c1f473..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_csharp/build_interop_stress.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds C# interop server and client in a base image. -set -e - -mkdir -p /var/local/git -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# Copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -cd /var/local/git/grpc - -# Build C++ metrics client (to query the metrics from csharp stress client) -make metrics_client -j - -# Build C# interop client & server -tools/run_tests/run_tests.py -l csharp -c dbg --build_only - diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile deleted file mode 100644 index d0f66d9955623c6714800aabd00a59feec761edb..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_cxx/Dockerfile +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright 2015-2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - -#================= -# C++ dependencies -RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -#================= -# Update clang to a version with improved tsan and fuzzing capabilities - -RUN apt-get update && apt-get -y install python cmake && apt-get clean - -RUN git clone -n -b release_38 http://llvm.org/git/llvm.git && \ - cd llvm && git checkout ad57503 && cd .. -RUN git clone -n -b release_38 http://llvm.org/git/clang.git && \ - cd clang && git checkout ad2c56e && cd .. -RUN git clone -n -b release_38 http://llvm.org/git/compiler-rt.git && \ - cd compiler-rt && git checkout 3176922 && cd .. -RUN git clone -n -b release_38 \ - http://llvm.org/git/clang-tools-extra.git && cd clang-tools-extra && \ - git checkout c288525 && cd .. -RUN git clone -n -b release_38 http://llvm.org/git/libcxx.git && \ - cd libcxx && git checkout fda3549 && cd .. -RUN git clone -n -b release_38 http://llvm.org/git/libcxxabi.git && \ - cd libcxxabi && git checkout 8d4e51d && cd .. - -RUN mv clang llvm/tools -RUN mv compiler-rt llvm/projects -RUN mv clang-tools-extra llvm/tools/clang/tools -RUN mv libcxx llvm/projects -RUN mv libcxxabi llvm/projects - -RUN mkdir llvm-build -RUN cd llvm-build && cmake \ - -DCMAKE_BUILD_TYPE:STRING=Release \ - -DCMAKE_INSTALL_PREFIX:STRING=/usr \ - -DLLVM_TARGETS_TO_BUILD:STRING=X86 \ - ../llvm -RUN make -C llvm-build -j 12 && make -C llvm-build install && rm -rf llvm-build - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_cxx/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_cxx/build_interop_stress.sh deleted file mode 100755 index 92d1f80fe60dad2956df412bad3e49b872bf356b..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_cxx/build_interop_stress.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds C++ interop server and client in a base image. -set -e - -mkdir -p /var/local/git -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -cd /var/local/git/grpc - -make install-certs - -BUILD_TYPE=${BUILD_TYPE:=opt} - -# build C++ interop stress client, interop client and server -make CONFIG=$BUILD_TYPE stress_test metrics_client interop_client interop_server diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_go/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_go/build_interop_stress.sh deleted file mode 100755 index 9e4769cf3341e199206dace883b0207fcf8cd3fb..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_go/build_interop_stress.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds Go interop server, Stress client and metrics client in a base image. -set -e - -# Clone just the grpc-go source code without any dependencies. -# We are cloning from a local git repo that contains the right revision -# to test instead of using "go get" to download from Github directly. -git clone --recursive /var/local/jenkins/grpc-go src/google.golang.org/grpc - -# Clone the 'grpc' repo. We just need this for the wrapper scripts under -# grpc/tools/gcp/stress_tests -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -# Get dependencies from GitHub -# NOTE: once grpc-go dependencies change, this needs to be updated manually -# but we don't expect this to happen any time soon. -go get github.com/golang/protobuf/proto -go get golang.org/x/net/context -go get golang.org/x/net/trace -go get golang.org/x/oauth2 -go get google.golang.org/cloud - -# Build the interop server, stress client and stress metrics client -(cd src/google.golang.org/grpc/interop/server && go install) -(cd src/google.golang.org/grpc/stress/client && go install) -(cd src/google.golang.org/grpc/stress/metrics_client && go install) diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile deleted file mode 100644 index 229ea469c42fa0acd389018256bf4962948b7a77..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_java/Dockerfile +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - -#================= -# C++ dependencies -RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -# Install JDK 8 and Git -# -RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \ - echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \ - echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \ - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 - -RUN apt-get update && apt-get -y install \ - git \ - libapr1 \ - oracle-java8-installer \ - && \ - apt-get clean && rm -r /var/cache/oracle-jdk8-installer/ - -ENV JAVA_HOME /usr/lib/jvm/java-8-oracle -ENV PATH $PATH:$JAVA_HOME/bin - - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_java/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_java/build_interop_stress.sh deleted file mode 100755 index 0194860d101309dc54a75e3ac754dcf60164eb58..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_java/build_interop_stress.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds C++ interop server and client in a base image. -set -e - -mkdir -p /var/local/git -# grpc-java repo -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java - -# grpc repo (for metrics client and for the stress test wrapper scripts) -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# Copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -# First build the metrics client in grpc repo -cd /var/local/git/grpc -make metrics_client - -# Build all interop test targets (which includes interop server and stress test -# client) in grpc-java repo -cd /var/local/git/grpc-java -./gradlew :grpc-interop-testing:installDist -PskipCodegen=true diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile deleted file mode 100644 index 5fd0bc0eb2148937705a0984aea313df78c5bfcb..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_node/Dockerfile +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -#================== -# Node dependencies - -# Install nvm -RUN touch .profile -RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash -# Install all versions of node that we want to test -RUN /bin/bash -l -c "nvm install 0.12 && npm config set cache /tmp/npm-cache" -RUN /bin/bash -l -c "nvm install 4 && npm config set cache /tmp/npm-cache" -RUN /bin/bash -l -c "nvm install 5 && npm config set cache /tmp/npm-cache" -RUN /bin/bash -l -c "nvm alias default 4" -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - - -RUN mkdir /var/local/jenkins - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh deleted file mode 100755 index 4116f842ff1264198f27bc053d5e5d14fd00a439..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_node/build_interop_stress.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds Node interop server and client in a base image. -set -e - -mkdir -p /var/local/git -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -cd /var/local/git/grpc - -# build Node interop client & server -npm install -g node-gyp -npm install --unsafe-perm --build-from-source diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_php/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_php/Dockerfile deleted file mode 100644 index b5198b46529d102d4d92943c8b781996bb1f9bf7..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_php/Dockerfile +++ /dev/null @@ -1,125 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -#================== -# Ruby dependencies - -# Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 -RUN \curl -sSL https://get.rvm.io | bash -s stable - -# Install Ruby 2.1 -RUN /bin/bash -l -c "rvm install ruby-2.1" -RUN /bin/bash -l -c "rvm use --default ruby-2.1" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" -RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -#================= -# PHP dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - git php5 php5-dev phpunit unzip - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - - -RUN mkdir /var/local/jenkins - -# Install composer -RUN curl -sS https://getcomposer.org/installer | php -RUN mv composer.phar /usr/local/bin/composer - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_php/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_php/build_interop_stress.sh deleted file mode 100755 index e3cca085a4d7c6a93d021326244720fbffc052ba..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_php/build_interop_stress.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds PHP interop server and client in a base image. -set -ex - -mkdir -p /var/local/git -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -cd /var/local/git/grpc - -make install-certs - -# gRPC core and protobuf need to be installed -make install - -(cd src/php/ext/grpc && phpize && ./configure && make) - -(cd third_party/protobuf && make install) - -(cd src/php && php -d extension=ext/grpc/modules/grpc.so /usr/local/bin/composer install) - -(cd src/php && ./bin/generate_proto_php.sh) diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile deleted file mode 100644 index 8e1de51f33171cb2ea9005dc261a0390f7c443dd..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_python/Dockerfile +++ /dev/null @@ -1,103 +0,0 @@ -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - -#================= -# C++ dependencies -RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - - -RUN pip install coverage -RUN pip install oauth2client - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_python/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_python/build_interop_stress.sh deleted file mode 100755 index 1c7dc2bd577fc9c6ae630f3bb487de4b5b275de4..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_python/build_interop_stress.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds Python interop server and client in a base image. -set -e - -mkdir -p /var/local/git -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -cd /var/local/git/grpc -tools/run_tests/run_tests.py -l python -c opt --build_only - -# Build c++ interop client -make metrics_client -j - diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile b/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile deleted file mode 100644 index 9d291aac5830fed2d7e949dcf60cf645f9452d45..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_ruby/Dockerfile +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:jessie - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - -#================= -# C++ dependencies -RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean - -# Google Cloud platform API libraries -RUN apt-get update && apt-get install -y python-pip && apt-get clean -RUN pip install --upgrade google-api-python-client - - -#================== -# Ruby dependencies - -# Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 -RUN \curl -sSL https://get.rvm.io | bash -s stable - -# Install Ruby 2.1 -RUN /bin/bash -l -c "rvm install ruby-2.1" -RUN /bin/bash -l -c "rvm use --default ruby-2.1" -RUN /bin/bash -l -c "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" -RUN /bin/bash -l -c "echo 'export PATH=/usr/local/rvm/bin:$PATH' >> ~/.bashrc" -RUN /bin/bash -l -c "echo 'rvm --default use ruby-2.1' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-ri --no-rdoc" - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/stress_test/grpc_interop_stress_ruby/build_interop_stress.sh b/tools/dockerfile/stress_test/grpc_interop_stress_ruby/build_interop_stress.sh deleted file mode 100755 index 019f0a44e4c1ec60bbf782ee9190936a2bb5cd9c..0000000000000000000000000000000000000000 --- a/tools/dockerfile/stress_test/grpc_interop_stress_ruby/build_interop_stress.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Builds Ruby interop server and client in a base image. -set -e - -mkdir -p /var/local/git -git clone /var/local/jenkins/grpc /var/local/git/grpc -# clone gRPC submodules, use data from locally cloned submodules where possible -(cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ -&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \ -${name}') - -# Copy service account keys if available -cp -r /var/local/jenkins/service_account $HOME || true - -cd /var/local/git/grpc -rvm --default use ruby-2.1 - -# Build Ruby interop client and server -(cd src/ruby && gem update bundler && bundle && rake compile) - -# Build c++ metrics client to query the metrics from ruby stress client -make metrics_client -j - diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 6ea8ef316c6fe8cf749e1e9df721bee265ff7574..c5627049442515ab6e6c53cce55da9bb50bb1305 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -27,46 +27,22 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -FROM ubuntu:15.10 +FROM gcr.io/oss-fuzz-base/base-builder -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ +# Install basic packages and Bazel dependencies. +RUN apt-get update && apt-get install -y software-properties-common python-software-properties +RUN add-apt-repository ppa:webupd8team/java +RUN apt-get update && apt-get -y install \ autoconf \ - autotools-dev \ build-essential \ - bzip2 \ - ccache \ curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ libtool \ make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - + openjdk-8-jdk \ + vim #======================== # Bazel installation -RUN apt-get install -y software-properties-common g++ RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" > /etc/apt/sources.list.d/bazel.list RUN curl https://bazel.build/bazel-release.pub.gpg | apt-key add - RUN apt-get -y update diff --git a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile index f9e709dccb1fbfc6a9bc0aa4ae28f7742f76838f..0b21a222263df8dc0c57b5a39a29520a89a4e096 100644 --- a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile index 4bb97c7aa9e5b97048df3b47ce6c30a076e77d9f..d9dc272a1b293fefe8f3de60ada749f2c296ec94 100644 --- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile index c4b710b5dfb96c842b6f8c0d9d4d5ffbd3479945..11ef52d1c066702e25bb666b212d121295b24c1e 100644 --- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile index bd742dff341732c5a13e2e63165520780ce72f75..41d3b2b520cb03d7393c3540dd26d03b0954fac0 100644 --- a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile index bc46b3055a6df1b54f8ad79c5bd141716052b59c..23d6fb8c41180e14b1247278278857031acda3c3 100644 --- a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/cxx_wheezy_x64/Dockerfile b/tools/dockerfile/test/cxx_wheezy_x64/Dockerfile deleted file mode 100644 index f7d7f542c11e61f0f2b0aee4191d55b43b8af63a..0000000000000000000000000000000000000000 --- a/tools/dockerfile/test/cxx_wheezy_x64/Dockerfile +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -FROM debian:wheezy - -# Install Git and basic packages. -RUN apt-get update && apt-get install -y \ - autoconf \ - autotools-dev \ - build-essential \ - bzip2 \ - ccache \ - curl \ - gcc \ - gcc-multilib \ - git \ - golang \ - gyp \ - lcov \ - libc6 \ - libc6-dbg \ - libc6-dev \ - libgtest-dev \ - libtool \ - make \ - perl \ - strace \ - python-dev \ - python-setuptools \ - python-yaml \ - telnet \ - unzip \ - wget \ - zip && apt-get clean - -#================ -# Build profiling -RUN apt-get update && apt-get install -y time && apt-get clean - -#==================== -# Python dependencies - -# Install dependencies - -RUN apt-get update && apt-get install -y \ - python-all-dev \ - python3-all-dev \ - python-pip - -# Install Python packages from PyPI -RUN pip install pip --upgrade -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.2.0 six==1.10.0 - -#================= -# C++ dependencies -RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev clang && apt-get clean - - -RUN apt-get update && apt-get install -y \ - gcc-4.4 \ - gcc-4.4-multilib \ - g++-4.4 \ - g++-4.4-multilib - -# set up backport to allow installation of Git version > 1.7 -RUN echo "deb http://http.debian.net/debian wheezy-backports main" >/etc/apt/sources.list.d/wheezy-backports.list -RUN apt-get update -qq -RUN apt-get -t wheezy-backports install -qq git - -RUN wget https://openssl.org/source/old/1.0.2/openssl-1.0.2f.tar.gz - -ENV POST_GIT_STEP tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh - -# Prepare ccache -RUN ln -s /usr/bin/ccache /usr/local/bin/gcc -RUN ln -s /usr/bin/ccache /usr/local/bin/g++ -RUN ln -s /usr/bin/ccache /usr/local/bin/cc -RUN ln -s /usr/bin/ccache /usr/local/bin/c++ -RUN ln -s /usr/bin/ccache /usr/local/bin/clang -RUN ln -s /usr/bin/ccache /usr/local/bin/clang++ - - -RUN mkdir /var/local/jenkins - -# Define the default command. -CMD ["bash"] diff --git a/tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh b/tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh deleted file mode 100755 index dfde93b1bd253a619696551bb1f2d289733427e6..0000000000000000000000000000000000000000 --- a/tools/dockerfile/test/cxx_wheezy_x64/post-git-setup.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -cd /var/local/git/grpc -cp /openssl-1.0.2f.tar.gz third_party -./tools/openssl/use_openssl.sh diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile index b398b70b64fff8704d88f734050f6267d587e4e2..4200ba0b266fd00560e83f68eec271e4b75066cb 100644 --- a/tools/dockerfile/test/fuzzer/Dockerfile +++ b/tools/dockerfile/test/fuzzer/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile index c1cce0a1417097fe4a6a4790c0789d692d800dc6..9b50d85e2f3906d0a1b9219d3c9718b9ef9ddf79 100644 --- a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #================ # C# dependencies diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile index 4595aa6bea1235ff62374f04751b4d19e1297950..deef892952921cb3f99590f711a3fe6ed79345e6 100644 --- a/tools/dockerfile/test/node_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + # Install Electron apt dependencies RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile index 0e2c103afd137da4184773c676a482ac357d2eda..6057c2d6eb8a2f614df3e9d3654c34dc394926e6 100644 --- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile @@ -75,6 +75,10 @@ RUN cd /var/local/git/php-src \ && make \ && make install +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile index c6f3dde39a5cc86ab284975316f663fb859f97db..1510c3649c3e7927516b39b8c17b7c7abd0eed60 100644 --- a/tools/dockerfile/test/php_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/python_jessie_x64/Dockerfile b/tools/dockerfile/test/python_jessie_x64/Dockerfile index 94c17078d342177cea1b330709e38a35a08d621f..cc69f4b5cd5a936ba0b3d53d98005d232af1304e 100644 --- a/tools/dockerfile/test/python_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/python_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/python_pyenv_x64/Dockerfile b/tools/dockerfile/test/python_pyenv_x64/Dockerfile index 435a9fdc978feb2accde7745c25057c78de94709..a105d334da7df5237df35c93692dae5533ce1bd7 100644 --- a/tools/dockerfile/test/python_pyenv_x64/Dockerfile +++ b/tools/dockerfile/test/python_pyenv_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile index 679c8ff47a699c66a01959c0d248aa905f04fc78..0a5c9a633d50b1142e66a2e1fdaac75b82e53779 100644 --- a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index 0da2a1914acffb92cb7784c8c949ce2e92a8437b..76923303ea483f1f72b393036acdfbbd6a31fcdf 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -63,6 +63,10 @@ RUN apt-get update && apt-get install -y \ # Build profiling RUN apt-get update && apt-get install -y time && apt-get clean +# Google Cloud platform API libraries +RUN apt-get update && apt-get install -y python-pip && apt-get clean +RUN pip install --upgrade google-api-python-client + #==================== # Python dependencies diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 9664234f9f4d0855e37c280d6bb79b7eaf94e91d..321417905bd756950ee7b99396934b49e2a78f20 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -939,8 +939,16 @@ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/error.h \ src/core/lib/iomgr/error_internal.h \ -src/core/lib/iomgr/ev_epoll_linux.c \ -src/core/lib/iomgr/ev_epoll_linux.h \ +src/core/lib/iomgr/ev_epoll1_linux.c \ +src/core/lib/iomgr/ev_epoll1_linux.h \ +src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ +src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h \ +src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ +src/core/lib/iomgr/ev_epoll_thread_pool_linux.h \ +src/core/lib/iomgr/ev_epollex_linux.c \ +src/core/lib/iomgr/ev_epollex_linux.h \ +src/core/lib/iomgr/ev_epollsig_linux.c \ +src/core/lib/iomgr/ev_epollsig_linux.h \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.c \ @@ -958,6 +966,8 @@ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_posix.h \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ +src/core/lib/iomgr/is_epollexclusive_available.c \ +src/core/lib/iomgr/is_epollexclusive_available.h \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/load_file.h \ src/core/lib/iomgr/lockfree_event.c \ @@ -1000,6 +1010,7 @@ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/socket_windows.h \ +src/core/lib/iomgr/sys_epoll_wrapper.h \ src/core/lib/iomgr/tcp_client.h \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_posix.h \ @@ -1026,6 +1037,8 @@ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_generic.h \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_heap.h \ +src/core/lib/iomgr/timer_manager.c \ +src/core/lib/iomgr/timer_manager.h \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/timer_uv.h \ src/core/lib/iomgr/udp_server.c \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 946953c00c301c8a49c19652979b884b22a2b11d..d344b951f6c7f8fd91bcc0d2c2f6a2b832c9072c 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1083,8 +1083,16 @@ src/core/lib/iomgr/endpoint_pair_windows.c \ src/core/lib/iomgr/error.c \ src/core/lib/iomgr/error.h \ src/core/lib/iomgr/error_internal.h \ -src/core/lib/iomgr/ev_epoll_linux.c \ -src/core/lib/iomgr/ev_epoll_linux.h \ +src/core/lib/iomgr/ev_epoll1_linux.c \ +src/core/lib/iomgr/ev_epoll1_linux.h \ +src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c \ +src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h \ +src/core/lib/iomgr/ev_epoll_thread_pool_linux.c \ +src/core/lib/iomgr/ev_epoll_thread_pool_linux.h \ +src/core/lib/iomgr/ev_epollex_linux.c \ +src/core/lib/iomgr/ev_epollex_linux.h \ +src/core/lib/iomgr/ev_epollsig_linux.c \ +src/core/lib/iomgr/ev_epollsig_linux.h \ src/core/lib/iomgr/ev_poll_posix.c \ src/core/lib/iomgr/ev_poll_posix.h \ src/core/lib/iomgr/ev_posix.c \ @@ -1102,6 +1110,8 @@ src/core/lib/iomgr/iomgr_posix.c \ src/core/lib/iomgr/iomgr_posix.h \ src/core/lib/iomgr/iomgr_uv.c \ src/core/lib/iomgr/iomgr_windows.c \ +src/core/lib/iomgr/is_epollexclusive_available.c \ +src/core/lib/iomgr/is_epollexclusive_available.h \ src/core/lib/iomgr/load_file.c \ src/core/lib/iomgr/load_file.h \ src/core/lib/iomgr/lockfree_event.c \ @@ -1144,6 +1154,7 @@ src/core/lib/iomgr/socket_utils_uv.c \ src/core/lib/iomgr/socket_utils_windows.c \ src/core/lib/iomgr/socket_windows.c \ src/core/lib/iomgr/socket_windows.h \ +src/core/lib/iomgr/sys_epoll_wrapper.h \ src/core/lib/iomgr/tcp_client.h \ src/core/lib/iomgr/tcp_client_posix.c \ src/core/lib/iomgr/tcp_client_posix.h \ @@ -1170,6 +1181,8 @@ src/core/lib/iomgr/timer_generic.c \ src/core/lib/iomgr/timer_generic.h \ src/core/lib/iomgr/timer_heap.c \ src/core/lib/iomgr/timer_heap.h \ +src/core/lib/iomgr/timer_manager.c \ +src/core/lib/iomgr/timer_manager.h \ src/core/lib/iomgr/timer_uv.c \ src/core/lib/iomgr/timer_uv.h \ src/core/lib/iomgr/udp_server.c \ diff --git a/tools/gce/create_linux_worker.sh b/tools/gce/create_linux_worker.sh index 322a592c073d27014b0aee18be774dcd21b5a219..b934f22a67316955595928b7372cb5dc24b09deb 100755 --- a/tools/gce/create_linux_worker.sh +++ b/tools/gce/create_linux_worker.sh @@ -45,7 +45,8 @@ gcloud compute instances create $INSTANCE_NAME \ --machine-type n1-standard-16 \ --image=ubuntu-1510 \ --image-project=grpc-testing \ - --boot-disk-size 1000 + --boot-disk-size 1000 \ + --scopes https://www.googleapis.com/auth/bigquery echo 'Created GCE instance, waiting 60 seconds for it to come online.' sleep 60 diff --git a/tools/gce/linux_worker_init.sh b/tools/gce/linux_worker_init.sh index d552343bde611917ef4a457f788d23c285651a8d..f795980aa833ce96a1c97e5ba7fb8d0e50eca177 100755 --- a/tools/gce/linux_worker_init.sh +++ b/tools/gce/linux_worker_init.sh @@ -61,6 +61,10 @@ sudo usermod -aG docker jenkins # see https://github.com/grpc/grpc/issues/4988 printf "{\n\t\"storage-driver\": \"overlay\"\n}" | sudo tee /etc/docker/daemon.json +# Install pip and Google API library to enable using GCP services +sudo apt-get install -y python-pip +sudo pip install google-api-python-client + # Install RVM # TODO(jtattermusch): why is RVM needed? gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 diff --git a/tools/gcp/stress_test/run_client.py b/tools/gcp/stress_test/run_client.py deleted file mode 100755 index 51ada6820da6bc91f93f5aa5aeb51da4cba02258..0000000000000000000000000000000000000000 --- a/tools/gcp/stress_test/run_client.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python2.7 -# Copyright 2015-2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import datetime -import os -import re -import resource -import select -import subprocess -import sys -import time - -from stress_test_utils import EventType -from stress_test_utils import BigQueryHelper - - -# TODO (sree): Write a python grpc client to directly query the metrics instead -# of calling metrics_client -def _get_qps(metrics_cmd): - qps = 0 - try: - # Note: gpr_log() writes even non-error messages to stderr stream. So it is - # important that we set stderr=subprocess.STDOUT - p = subprocess.Popen(args=metrics_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - retcode = p.wait() - (out_str, err_str) = p.communicate() - if retcode != 0: - print 'Error in reading metrics information' - print 'Output: ', out_str - else: - # The overall qps is printed at the end of the line - m = re.search('\d+$', out_str) - qps = int(m.group()) if m else 0 - except Exception as ex: - print 'Exception while reading metrics information: ' + str(ex) - return qps - - -def run_client(): - """This is a wrapper around the stress test client and performs the following: - 1) Create the following two tables in Big Query: - (i) Summary table: To record events like the test started, completed - successfully or failed - (ii) Qps table: To periodically record the QPS sent by this client - 2) Start the stress test client and add a row in the Big Query summary - table - 3) Once every few seconds (as specificed by the poll_interval_secs) poll - the status of the stress test client process and perform the - following: - 3.1) If the process is still running, get the current qps by invoking - the metrics client program and add a row in the Big Query - Qps table. Sleep for a duration specified by poll_interval_secs - 3.2) If the process exited successfully, add a row in the Big Query - Summary table and exit - 3.3) If the process failed, add a row in Big Query summary table and - wait forever. - NOTE: This script typically runs inside a GKE pod which means - that the pod gets destroyed when the script exits. However, in - case the stress test client fails, we would not want the pod to - be destroyed (since we might want to connect to the pod for - examining logs). This is the reason why the script waits forever - in case of failures - """ - # Set the 'core file' size to 'unlimited' so that 'core' files are generated - # if the client crashes (Note: This is not relevant for Java and Go clients) - resource.setrlimit(resource.RLIMIT_CORE, - (resource.RLIM_INFINITY, resource.RLIM_INFINITY)) - - env = dict(os.environ) - image_type = env['STRESS_TEST_IMAGE_TYPE'] - stress_client_cmd = env['STRESS_TEST_CMD'].split() - args_str = env['STRESS_TEST_ARGS_STR'] - metrics_client_cmd = env['METRICS_CLIENT_CMD'].split() - metrics_client_args_str = env['METRICS_CLIENT_ARGS_STR'] - run_id = env['RUN_ID'] - pod_name = env['POD_NAME'] - logfile_name = env.get('LOGFILE_NAME') - poll_interval_secs = float(env['POLL_INTERVAL_SECS']) - project_id = env['GCP_PROJECT_ID'] - dataset_id = env['DATASET_ID'] - summary_table_id = env['SUMMARY_TABLE_ID'] - qps_table_id = env['QPS_TABLE_ID'] - # The following parameter is to inform us whether the stress client runs - # forever until forcefully stopped or will it naturally stop after sometime. - # This way, we know that the stress client process should not terminate (even - # if it does with a success exit code) and flag the termination as a failure - will_run_forever = env.get('WILL_RUN_FOREVER', '1') - - bq_helper = BigQueryHelper(run_id, image_type, pod_name, project_id, - dataset_id, summary_table_id, qps_table_id) - bq_helper.initialize() - - # Create BigQuery Dataset and Tables: Summary Table and Metrics Table - if not bq_helper.setup_tables(): - print 'Error in creating BigQuery tables' - return - - start_time = datetime.datetime.now() - - logfile = None - details = 'Logging to stdout' - if logfile_name is not None: - print 'Opening logfile: %s ...' % logfile_name - details = 'Logfile: %s' % logfile_name - logfile = open(logfile_name, 'w') - - metrics_cmd = metrics_client_cmd + [x - for x in metrics_client_args_str.split()] - stress_cmd = stress_client_cmd + [x for x in args_str.split()] - - details = '%s, Metrics command: %s, Stress client command: %s' % ( - details, str(metrics_cmd), str(stress_cmd)) - # Update status that the test is starting (in the status table) - bq_helper.insert_summary_row(EventType.STARTING, details) - - print 'Launching process %s ...' % stress_cmd - stress_p = subprocess.Popen(args=stress_cmd, - stdout=logfile, - stderr=subprocess.STDOUT) - - qps_history = [1, 1, 1] # Maintain the last 3 qps readings - qps_history_idx = 0 # Index into the qps_history list - - is_running_status_written = False - is_error = False - while True: - # Check if stress_client is still running. If so, collect metrics and upload - # to BigQuery status table - # If stress_p.poll() is not None, it means that the stress client terminated - if stress_p.poll() is not None: - end_time = datetime.datetime.now().isoformat() - event_type = EventType.SUCCESS - details = 'End time: %s' % end_time - if will_run_forever == '1' or stress_p.returncode != 0: - event_type = EventType.FAILURE - details = 'Return code = %d. End time: %s' % (stress_p.returncode, - end_time) - is_error = True - bq_helper.insert_summary_row(event_type, details) - print details - break - - if not is_running_status_written: - bq_helper.insert_summary_row(EventType.RUNNING, '') - is_running_status_written = True - - # Stress client still running. Get metrics - qps = _get_qps(metrics_cmd) - qps_recorded_at = datetime.datetime.now().isoformat() - print 'qps: %d at %s' % (qps, qps_recorded_at) - - # If QPS has been zero for the last 3 iterations, flag it as error and exit - qps_history[qps_history_idx] = qps - qps_history_idx = (qps_history_idx + 1) % len(qps_history) - if sum(qps_history) == 0: - details = 'QPS has been zero for the last %d seconds - as of : %s' % ( - poll_interval_secs * 3, qps_recorded_at) - is_error = True - bq_helper.insert_summary_row(EventType.FAILURE, details) - print details - break - - # Upload qps metrics to BiqQuery - bq_helper.insert_qps_row(qps, qps_recorded_at) - - time.sleep(poll_interval_secs) - - if is_error: - print 'Waiting indefinitely..' - select.select([], [], []) - - print 'Completed' - return - - -if __name__ == '__main__': - run_client() diff --git a/tools/gcp/stress_test/run_ruby.sh b/tools/gcp/stress_test/run_ruby.sh deleted file mode 100755 index 80d0567447b54a83b91ea439efd09f97a6042b67..0000000000000000000000000000000000000000 --- a/tools/gcp/stress_test/run_ruby.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash -# Copyright 2015-2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# This is a wrapper script that was created to help run_server.py and -# run_client.py to launch 'node js' stress clients and stress servers -source /etc/profile.d/rvm.sh - -set -ex - -$@ diff --git a/tools/gcp/stress_test/run_server.py b/tools/gcp/stress_test/run_server.py deleted file mode 100755 index 8f47e42ef32dd0425cea419b80b41b7f04db45d6..0000000000000000000000000000000000000000 --- a/tools/gcp/stress_test/run_server.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python2.7 -# Copyright 2015-2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import datetime -import os -import resource -import select -import subprocess -import sys -import time - -from stress_test_utils import BigQueryHelper -from stress_test_utils import EventType - - -def run_server(): - """This is a wrapper around the interop server and performs the following: - 1) Create a 'Summary table' in Big Query to record events like the server - started, completed successfully or failed. NOTE: This also creates - another table called the QPS table which is currently NOT needed on the - server (it is needed on the stress test clients) - 2) Start the server process and add a row in Big Query summary table - 3) Wait for the server process to terminate. The server process does not - terminate unless there is an error. - If the server process terminated with a failure, add a row in Big Query - and wait forever. - NOTE: This script typically runs inside a GKE pod which means that the - pod gets destroyed when the script exits. However, in case the server - process fails, we would not want the pod to be destroyed (since we - might want to connect to the pod for examining logs). This is the - reason why the script waits forever in case of failures. - """ - # Set the 'core file' size to 'unlimited' so that 'core' files are generated - # if the server crashes (Note: This is not relevant for Java and Go servers) - resource.setrlimit(resource.RLIMIT_CORE, - (resource.RLIM_INFINITY, resource.RLIM_INFINITY)) - - # Read the parameters from environment variables - env = dict(os.environ) - - run_id = env['RUN_ID'] # The unique run id for this test - image_type = env['STRESS_TEST_IMAGE_TYPE'] - stress_server_cmd = env['STRESS_TEST_CMD'].split() - args_str = env['STRESS_TEST_ARGS_STR'] - pod_name = env['POD_NAME'] - project_id = env['GCP_PROJECT_ID'] - dataset_id = env['DATASET_ID'] - summary_table_id = env['SUMMARY_TABLE_ID'] - qps_table_id = env['QPS_TABLE_ID'] - # The following parameter is to inform us whether the server runs forever - # until forcefully stopped or will it naturally stop after sometime. - # This way, we know that the process should not terminate (even if it does - # with a success exit code) and flag any termination as a failure. - will_run_forever = env.get('WILL_RUN_FOREVER', '1') - - logfile_name = env.get('LOGFILE_NAME') - - print('pod_name: %s, project_id: %s, run_id: %s, dataset_id: %s, ' - 'summary_table_id: %s, qps_table_id: %s') % (pod_name, project_id, - run_id, dataset_id, - summary_table_id, - qps_table_id) - - bq_helper = BigQueryHelper(run_id, image_type, pod_name, project_id, - dataset_id, summary_table_id, qps_table_id) - bq_helper.initialize() - - # Create BigQuery Dataset and Tables: Summary Table and Metrics Table - if not bq_helper.setup_tables(): - print 'Error in creating BigQuery tables' - return - - start_time = datetime.datetime.now() - - logfile = None - details = 'Logging to stdout' - if logfile_name is not None: - print 'Opening log file: ', logfile_name - logfile = open(logfile_name, 'w') - details = 'Logfile: %s' % logfile_name - - stress_cmd = stress_server_cmd + [x for x in args_str.split()] - - details = '%s, Stress server command: %s' % (details, str(stress_cmd)) - # Update status that the test is starting (in the status table) - bq_helper.insert_summary_row(EventType.STARTING, details) - - print 'Launching process %s ...' % stress_cmd - stress_p = subprocess.Popen(args=stress_cmd, - stdout=logfile, - stderr=subprocess.STDOUT) - - # Update the status to running if subprocess.Popen launched the server - if stress_p.poll() is None: - bq_helper.insert_summary_row(EventType.RUNNING, '') - - # Wait for the server process to terminate - returncode = stress_p.wait() - - if will_run_forever == '1' or returncode != 0: - end_time = datetime.datetime.now().isoformat() - event_type = EventType.FAILURE - details = 'Returncode: %d; End time: %s' % (returncode, end_time) - bq_helper.insert_summary_row(event_type, details) - print 'Waiting indefinitely..' - select.select([], [], []) - return returncode - - -if __name__ == '__main__': - run_server() diff --git a/tools/gcp/stress_test/stress_test_utils.py b/tools/gcp/stress_test/stress_test_utils.py deleted file mode 100755 index be50af31845f77fafcae5681ce0f8c6a8692a127..0000000000000000000000000000000000000000 --- a/tools/gcp/stress_test/stress_test_utils.py +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env python2.7 -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import datetime -import json -import os -import re -import select -import subprocess -import sys -import time - -# Import big_query_utils module -bq_utils_dir = os.path.abspath(os.path.join( - os.path.dirname(__file__), '../utils')) -sys.path.append(bq_utils_dir) -import big_query_utils as bq_utils - - -class EventType: - STARTING = 'STARTING' - RUNNING = 'RUNNING' - SUCCESS = 'SUCCESS' - FAILURE = 'FAILURE' - - -class BigQueryHelper: - """Helper class for the stress test wrappers to interact with BigQuery. - """ - - def __init__(self, run_id, image_type, pod_name, project_id, dataset_id, - summary_table_id, qps_table_id): - self.run_id = run_id - self.image_type = image_type - self.pod_name = pod_name - self.project_id = project_id - self.dataset_id = dataset_id - self.summary_table_id = summary_table_id - self.qps_table_id = qps_table_id - - def initialize(self): - self.bq = bq_utils.create_big_query() - - def setup_tables(self): - return bq_utils.create_dataset(self.bq, self.project_id, self.dataset_id) \ - and self.__create_summary_table() \ - and self.__create_qps_table() - - def insert_summary_row(self, event_type, details): - row_values_dict = { - 'run_id': self.run_id, - 'image_type': self.image_type, - 'pod_name': self.pod_name, - 'event_date': datetime.datetime.now().isoformat(), - 'event_type': event_type, - 'details': details - } - # row_unique_id is something that uniquely identifies the row (BigQuery uses - # it for duplicate detection). - row_unique_id = '%s_%s_%s' % (self.run_id, self.pod_name, event_type) - row = bq_utils.make_row(row_unique_id, row_values_dict) - return bq_utils.insert_rows(self.bq, self.project_id, self.dataset_id, - self.summary_table_id, [row]) - - def insert_qps_row(self, qps, recorded_at): - row_values_dict = { - 'run_id': self.run_id, - 'pod_name': self.pod_name, - 'recorded_at': recorded_at, - 'qps': qps - } - - # row_unique_id is something that uniquely identifies the row (BigQuery uses - # it for duplicate detection). - row_unique_id = '%s_%s_%s' % (self.run_id, self.pod_name, recorded_at) - row = bq_utils.make_row(row_unique_id, row_values_dict) - return bq_utils.insert_rows(self.bq, self.project_id, self.dataset_id, - self.qps_table_id, [row]) - - def check_if_any_tests_failed(self, num_query_retries=3, timeout_msec=30000): - query = ('SELECT event_type FROM %s.%s WHERE run_id = \'%s\' AND ' - 'event_type="%s"') % (self.dataset_id, self.summary_table_id, - self.run_id, EventType.FAILURE) - page = None - try: - query_job = bq_utils.sync_query_job(self.bq, self.project_id, query) - job_id = query_job['jobReference']['jobId'] - project_id = query_job['jobReference']['projectId'] - page = self.bq.jobs().getQueryResults( - projectId=project_id, - jobId=job_id, - timeoutMs=timeout_msec).execute(num_retries=num_query_retries) - - if not page['jobComplete']: - print('TIMEOUT ERROR: The query %s timed out. Current timeout value is' - ' %d msec. Returning False (i.e assuming there are no failures)' - ) % (query, timeout_msec) - return False - - num_failures = int(page['totalRows']) - print 'num rows: ', num_failures - return num_failures > 0 - except: - print 'Exception in check_if_any_tests_failed(). Info: ', sys.exc_info() - print 'Query: ', query - - def print_summary_records(self, num_query_retries=3): - line = '-' * 120 - print line - print 'Summary records' - print 'Run Id: ', self.run_id - print 'Dataset Id: ', self.dataset_id - print line - query = ('SELECT pod_name, image_type, event_type, event_date, details' - ' FROM %s.%s WHERE run_id = \'%s\' ORDER by event_date;') % ( - self.dataset_id, self.summary_table_id, self.run_id) - query_job = bq_utils.sync_query_job(self.bq, self.project_id, query) - - print '{:<25} {:<12} {:<12} {:<30} {}'.format('Pod name', 'Image type', - 'Event type', 'Date', - 'Details') - print line - page_token = None - while True: - page = self.bq.jobs().getQueryResults( - pageToken=page_token, - **query_job['jobReference']).execute(num_retries=num_query_retries) - rows = page.get('rows', []) - for row in rows: - print '{:<25} {:<12} {:<12} {:<30} {}'.format(row['f'][0]['v'], - row['f'][1]['v'], - row['f'][2]['v'], - row['f'][3]['v'], - row['f'][4]['v']) - page_token = page.get('pageToken') - if not page_token: - break - - def print_qps_records(self, num_query_retries=3): - line = '-' * 80 - print line - print 'QPS Summary' - print 'Run Id: ', self.run_id - print 'Dataset Id: ', self.dataset_id - print line - query = ( - 'SELECT pod_name, recorded_at, qps FROM %s.%s WHERE run_id = \'%s\' ' - 'ORDER by recorded_at;') % (self.dataset_id, self.qps_table_id, - self.run_id) - query_job = bq_utils.sync_query_job(self.bq, self.project_id, query) - print '{:<25} {:30} {}'.format('Pod name', 'Recorded at', 'Qps') - print line - page_token = None - while True: - page = self.bq.jobs().getQueryResults( - pageToken=page_token, - **query_job['jobReference']).execute(num_retries=num_query_retries) - rows = page.get('rows', []) - for row in rows: - print '{:<25} {:30} {}'.format(row['f'][0]['v'], row['f'][1]['v'], - row['f'][2]['v']) - page_token = page.get('pageToken') - if not page_token: - break - - def __create_summary_table(self): - summary_table_schema = [ - ('run_id', 'STRING', 'Test run id'), - ('image_type', 'STRING', 'Client or Server?'), - ('pod_name', 'STRING', 'GKE pod hosting this image'), - ('event_date', 'STRING', 'The date of this event'), - ('event_type', 'STRING', 'STARTING/RUNNING/SUCCESS/FAILURE'), - ('details', 'STRING', 'Any other relevant details') - ] - desc = ('The table that contains STARTING/RUNNING/SUCCESS/FAILURE events ' - 'for the stress test clients and servers') - return bq_utils.create_table(self.bq, self.project_id, self.dataset_id, - self.summary_table_id, summary_table_schema, - desc) - - def __create_qps_table(self): - qps_table_schema = [ - ('run_id', 'STRING', 'Test run id'), - ('pod_name', 'STRING', 'GKE pod hosting this image'), - ('recorded_at', 'STRING', 'Metrics recorded at time'), - ('qps', 'INTEGER', 'Queries per second') - ] - desc = 'The table that cointains the qps recorded at various intervals' - return bq_utils.create_table(self.bq, self.project_id, self.dataset_id, - self.qps_table_id, qps_table_schema, desc) diff --git a/tools/gcp/utils/kubernetes_api.py b/tools/gcp/utils/kubernetes_api.py deleted file mode 100755 index a8a4aad69b455342a7f1025ababbdd80b8dfb275..0000000000000000000000000000000000000000 --- a/tools/gcp/utils/kubernetes_api.py +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env python2.7 -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -import requests -import json - -_REQUEST_TIMEOUT_SECS = 10 - - -def _make_pod_config(pod_name, image_name, container_port_list, cmd_list, - arg_list, env_dict): - """Creates a string containing the Pod defintion as required by the Kubernetes API""" - body = { - 'kind': 'Pod', - 'apiVersion': 'v1', - 'metadata': { - 'name': pod_name, - 'labels': {'name': pod_name} - }, - 'spec': { - 'containers': [ - { - 'name': pod_name, - 'image': image_name, - 'ports': [{'containerPort': port, - 'protocol': 'TCP'} - for port in container_port_list], - 'imagePullPolicy': 'Always' - } - ] - } - } - - env_list = [{'name': k, 'value': v} for (k, v) in env_dict.iteritems()] - if len(env_list) > 0: - body['spec']['containers'][0]['env'] = env_list - - # Add the 'Command' and 'Args' attributes if they are passed. - # Note: - # - 'Command' overrides the ENTRYPOINT in the Docker Image - # - 'Args' override the CMD in Docker image (yes, it is confusing!) - if len(cmd_list) > 0: - body['spec']['containers'][0]['command'] = cmd_list - if len(arg_list) > 0: - body['spec']['containers'][0]['args'] = arg_list - return json.dumps(body) - - -def _make_service_config(service_name, pod_name, service_port_list, - container_port_list, is_headless): - """Creates a string containing the Service definition as required by the Kubernetes API. - - NOTE: - This creates either a Headless Service or 'LoadBalancer' service depending on - the is_headless parameter. For Headless services, there is no 'type' attribute - and the 'clusterIP' attribute is set to 'None'. Also, if the service is - Headless, Kubernetes creates DNS entries for Pods - i.e creates DNS A-records - mapping the service's name to the Pods' IPs - """ - if len(container_port_list) != len(service_port_list): - print( - 'ERROR: container_port_list and service_port_list must be of same size') - return '' - body = { - 'kind': 'Service', - 'apiVersion': 'v1', - 'metadata': { - 'name': service_name, - 'labels': { - 'name': service_name - } - }, - 'spec': { - 'ports': [], - 'selector': { - 'name': pod_name - } - } - } - # Populate the 'ports' list in the 'spec' section. This maps service ports - # (port numbers that are exposed by Kubernetes) to container ports (i.e port - # numbers that are exposed by your Docker image) - for idx in range(len(container_port_list)): - port_entry = { - 'port': service_port_list[idx], - 'targetPort': container_port_list[idx], - 'protocol': 'TCP' - } - body['spec']['ports'].append(port_entry) - - # Make this either a LoadBalancer service or a headless service depending on - # the is_headless parameter - if is_headless: - body['spec']['clusterIP'] = 'None' - else: - body['spec']['type'] = 'LoadBalancer' - return json.dumps(body) - - -def _print_connection_error(msg): - print('ERROR: Connection failed. Did you remember to run Kubenetes proxy on ' - 'localhost (i.e kubectl proxy --port=<proxy_port>) ?. Error: %s' % msg) - - -def _do_post(post_url, api_name, request_body): - """Helper to do HTTP POST. - - Note: - 1) On success, Kubernetes returns a success code of 201(CREATED) not 200(OK) - 2) A response code of 509(CONFLICT) is interpreted as a success code (since - the error is most likely due to the resource already existing). This makes - _do_post() idempotent which is semantically desirable. - """ - is_success = True - try: - r = requests.post(post_url, - data=request_body, - timeout=_REQUEST_TIMEOUT_SECS) - if r.status_code == requests.codes.conflict: - print('WARN: Looks like the resource already exists. Api: %s, url: %s' % - (api_name, post_url)) - elif r.status_code != requests.codes.created: - print('ERROR: %s API returned error. HTTP response: (%d) %s' % - (api_name, r.status_code, r.text)) - is_success = False - except (requests.exceptions.Timeout, - requests.exceptions.ConnectionError) as e: - is_success = False - _print_connection_error(str(e)) - return is_success - - -def _do_delete(del_url, api_name): - """Helper to do HTTP DELETE. - - Note: A response code of 404(NOT_FOUND) is treated as success to keep - _do_delete() idempotent. - """ - is_success = True - try: - r = requests.delete(del_url, timeout=_REQUEST_TIMEOUT_SECS) - if r.status_code == requests.codes.not_found: - print('WARN: The resource does not exist. Api: %s, url: %s' % - (api_name, del_url)) - elif r.status_code != requests.codes.ok: - print('ERROR: %s API returned error. HTTP response: %s' % - (api_name, r.text)) - is_success = False - except (requests.exceptions.Timeout, - requests.exceptions.ConnectionError) as e: - is_success = False - _print_connection_error(str(e)) - return is_success - - -def create_service(kube_host, kube_port, namespace, service_name, pod_name, - service_port_list, container_port_list, is_headless): - """Creates either a Headless Service or a LoadBalancer Service depending - on the is_headless parameter. - """ - post_url = 'http://%s:%d/api/v1/namespaces/%s/services' % ( - kube_host, kube_port, namespace) - request_body = _make_service_config(service_name, pod_name, service_port_list, - container_port_list, is_headless) - return _do_post(post_url, 'Create Service', request_body) - - -def create_pod(kube_host, kube_port, namespace, pod_name, image_name, - container_port_list, cmd_list, arg_list, env_dict): - """Creates a Kubernetes Pod. - - Note that it is generally NOT considered a good practice to directly create - Pods. Typically, the recommendation is to create 'Controllers' to create and - manage Pods' lifecycle. Currently Kubernetes only supports 'Replication - Controller' which creates a configurable number of 'identical Replicas' of - Pods and automatically restarts any Pods in case of failures (for eg: Machine - failures in Kubernetes). This makes it less flexible for our test use cases - where we might want slightly different set of args to each Pod. Hence we - directly create Pods and not care much about Kubernetes failures since those - are very rare. - """ - post_url = 'http://%s:%d/api/v1/namespaces/%s/pods' % (kube_host, kube_port, - namespace) - request_body = _make_pod_config(pod_name, image_name, container_port_list, - cmd_list, arg_list, env_dict) - return _do_post(post_url, 'Create Pod', request_body) - - -def delete_service(kube_host, kube_port, namespace, service_name): - del_url = 'http://%s:%d/api/v1/namespaces/%s/services/%s' % ( - kube_host, kube_port, namespace, service_name) - return _do_delete(del_url, 'Delete Service') - - -def delete_pod(kube_host, kube_port, namespace, pod_name): - del_url = 'http://%s:%d/api/v1/namespaces/%s/pods/%s' % (kube_host, kube_port, - namespace, pod_name) - return _do_delete(del_url, 'Delete Pod') - - -def create_pod_and_service(kube_host, kube_port, namespace, pod_name, - image_name, container_port_list, cmd_list, arg_list, - env_dict, is_headless_service): - """A helper function that creates a pod and a service (if pod creation was successful).""" - is_success = create_pod(kube_host, kube_port, namespace, pod_name, image_name, - container_port_list, cmd_list, arg_list, env_dict) - if not is_success: - print 'Error in creating Pod' - return False - - is_success = create_service( - kube_host, - kube_port, - namespace, - pod_name, # Use pod_name for service - pod_name, - container_port_list, # Service port list same as container port list - container_port_list, - is_headless_service) - if not is_success: - print 'Error in creating Service' - return False - - print 'Successfully created the pod/service %s' % pod_name - return True - - -def delete_pod_and_service(kube_host, kube_port, namespace, pod_name): - """ A helper function that calls delete_pod and delete_service """ - is_success = delete_pod(kube_host, kube_port, namespace, pod_name) - if not is_success: - print 'Error in deleting pod %s' % pod_name - return False - - # Note: service name assumed to the the same as pod name - is_success = delete_service(kube_host, kube_port, namespace, pod_name) - if not is_success: - print 'Error in deleting service %s' % pod_name - return False - - print 'Successfully deleted the Pod/Service: %s' % pod_name - return True diff --git a/tools/run_tests/stress_test/cleanup_docker_images.sh b/tools/internal_ci/helper_scripts/prepare_build_linux_rc old mode 100755 new mode 100644 similarity index 86% rename from tools/run_tests/stress_test/cleanup_docker_images.sh rename to tools/internal_ci/helper_scripts/prepare_build_linux_rc index e424fcfd99b27a0e165d5ad328d39dd86c07ccb9..c8cb5a0c40fbc406c08a4cbf0f57835f852fee26 --- a/tools/run_tests/stress_test/cleanup_docker_images.sh +++ b/tools/internal_ci/helper_scripts/prepare_build_linux_rc @@ -27,5 +27,13 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -for img in `docker images | grep \<none\> | awk '{print $3 }'` ; do docker rmi -f $img; done +# Source this rc script to prepare the environment for linux builds + +# Need to increase open files limit for c tests +ulimit -n 32768 + +# Download Docker images from DockerHub +export DOCKERHUB_ORGANIZATION=grpctesting + +git submodule update --init diff --git a/tools/internal_ci/linux/grpc_interop_badserver_java.sh b/tools/internal_ci/linux/grpc_interop_badserver_java.sh index c309c623e0b7968c329334c23c9019a27d7f30b4..02d7b9d43168babc18d11fe1b639a060f5b17ca3 100755 --- a/tools/internal_ci/linux/grpc_interop_badserver_java.sh +++ b/tools/internal_ci/linux/grpc_interop_badserver_java.sh @@ -35,7 +35,7 @@ export LANG=en_US.UTF-8 # Enter the gRPC repo root cd $(dirname $0)/../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc tools/run_tests/run_interop_tests.py -l java --use_docker --http2_server_interop $@ diff --git a/tools/internal_ci/linux/grpc_interop_badserver_python.sh b/tools/internal_ci/linux/grpc_interop_badserver_python.sh index c3bb92f33da34a3a5c8aadb6ba50bbf4faeabdb7..3ceb181d9048480623f1cbea92ffb609b6ee2817 100755 --- a/tools/internal_ci/linux/grpc_interop_badserver_python.sh +++ b/tools/internal_ci/linux/grpc_interop_badserver_python.sh @@ -35,7 +35,7 @@ export LANG=en_US.UTF-8 # Enter the gRPC repo root cd $(dirname $0)/../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc tools/run_tests/run_interop_tests.py -l python --use_docker --http2_server_interop $@ diff --git a/tools/internal_ci/linux/grpc_interop_tocloud.sh b/tools/internal_ci/linux/grpc_interop_tocloud.sh index 572001d9441241f7173f7ffd2fa09c199a17db75..a3067e70e67ae7e17897c1d773adc6ee58e5210d 100755 --- a/tools/internal_ci/linux/grpc_interop_tocloud.sh +++ b/tools/internal_ci/linux/grpc_interop_tocloud.sh @@ -35,6 +35,6 @@ export LANG=en_US.UTF-8 # Enter the gRPC repo root cd $(dirname $0)/../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc tools/run_tests/run_interop_tests.py -l all -s all --use_docker --http2_interop -t -j 12 $@ diff --git a/tools/internal_ci/linux/grpc_master.sh b/tools/internal_ci/linux/grpc_master.sh index bd22dd069c21857f971a1117b9df4d4202277b11..d3c89bfa0715f0f5fafcb4bdaadd087a3af6a05e 100755 --- a/tools/internal_ci/linux/grpc_master.sh +++ b/tools/internal_ci/linux/grpc_master.sh @@ -33,18 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../.. -# TODO(jtattermusch): get rid of the system inspection eventually -nproc || true -lsb_release -dc || true -gcc --version || true -clang --version || true -docker --version || true +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# Need to increase open files limit for c tests -ulimit -n 32768 - -git submodule update --init - -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f basictests linux --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/grpc_portability.sh b/tools/internal_ci/linux/grpc_portability.sh index 6c55ed71cbbee3cb1b7983c998fe2afb54b6aa14..64959c793f32e4ac326067d1a05e57e39b189160 100755 --- a/tools/internal_ci/linux/grpc_portability.sh +++ b/tools/internal_ci/linux/grpc_portability.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f portability linux --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/grpc_portability_build_only.sh b/tools/internal_ci/linux/grpc_portability_build_only.sh index 787f0302c088726ce0374256f5a34031e4bb9a75..099c3f8948ceeefbe2f84509a9f6ee14077b6a5e 100755 --- a/tools/internal_ci/linux/grpc_portability_build_only.sh +++ b/tools/internal_ci/linux/grpc_portability_build_only.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f portability linux --internal_ci --build_only diff --git a/tools/internal_ci/linux/grpc_sanity.sh b/tools/internal_ci/linux/grpc_sanity.sh index fac25c75315d2369e03311edefdfc8a1bc23b569..7166ce7d248985590a901c702c6aff40e037e59f 100755 --- a/tools/internal_ci/linux/grpc_sanity.sh +++ b/tools/internal_ci/linux/grpc_sanity.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download base docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests.py -l sanity -c opt -t -x sponge_log.xml --use_docker --report_suite_name sanity_linux_opt diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh index 2927ad7de485c39e37bbec7f587b06b62a3bc224..5a61d9d5d1b5c81596c6682ee8fca96a3e099818 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f c asan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh index 3a3c850a9f2502ead0cab85c2ff1c405814cb4cb..1c3b90dce223d83cd068817be644f4200de12316 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f c msan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh index daebf34521e98f6e8d221df27ee2bef3a665276f..495a004c9df04900ab39d3d1d90b2fb0bba17c2a 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f c tsan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh index 29f7fda74b1b489de705c0ba2ca26c23800f3e6d..99219e3515998bcea38e5198ecfdca35464e2d25 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f c++ asan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh index 4b9291a4a00ac8cf5bc14bdbe1fe11122f503a7c..be46af902c58cf5b10c3f669c213566676087943 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh @@ -33,8 +33,6 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../../.. -git submodule update --init +source tools/internal_ci/helper_scripts/prepare_build_linux_rc -# download docker images from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting tools/run_tests/run_tests_matrix.py -f c++ tsan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/jenkins/run_interop_stress.sh b/tools/jenkins/run_interop_stress.sh deleted file mode 100755 index 22d81db8bcdf217f0f65371301c6e0faae710518..0000000000000000000000000000000000000000 --- a/tools/jenkins/run_interop_stress.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# This script is invoked by Jenkins and runs interop test suite. -set -ex - -# Enter the gRPC repo root -cd $(dirname $0)/../.. - -tools/run_tests/run_stress_tests.py -l all -s all -j 12 $@ || true diff --git a/tools/profiling/microbenchmarks/bm_diff.py b/tools/profiling/microbenchmarks/bm_diff.py index b2d6f460475f44634b1f2b47893dc3cff0d8710c..299abb5fdb707467177fece08376ebe8c95b1751 100755 --- a/tools/profiling/microbenchmarks/bm_diff.py +++ b/tools/profiling/microbenchmarks/bm_diff.py @@ -56,6 +56,10 @@ _INTERESTING = ( 'writes_per_iteration', 'atm_cas_per_iteration', 'atm_add_per_iteration', + 'cli_transport_stalls_per_iteration', + 'cli_stream_stalls_per_iteration', + 'svr_transport_stalls_per_iteration', + 'svr_stream_stalls_per_iteration' 'nows_per_iteration', ) diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py index 04702baccaeba3afe99b21d18c2146e8acf24388..c90da066c349c1832c24495ff5604ce54cba8c65 100644 --- a/tools/run_tests/artifacts/artifact_targets.py +++ b/tools/run_tests/artifacts/artifact_targets.py @@ -202,6 +202,7 @@ class CSharpExtArtifact: 'EMBED_OPENSSL': 'true', 'EMBED_ZLIB': 'true', 'CFLAGS': '-DGPR_BACKWARDS_COMPATIBILITY_MODE', + 'CXXFLAGS': '-DGPR_BACKWARDS_COMPATIBILITY_MODE', 'LDFLAGS': ''} if self.platform == 'linux': return create_docker_jobspec(self.name, @@ -211,6 +212,7 @@ class CSharpExtArtifact: else: archflag = _ARCH_FLAG_MAP[self.arch] environ['CFLAGS'] += ' %s %s' % (archflag, _MACOS_COMPAT_FLAG) + environ['CXXFLAGS'] += ' %s %s' % (archflag, _MACOS_COMPAT_FLAG) environ['LDFLAGS'] += ' %s' % archflag return create_jobspec(self.name, ['tools/run_tests/artifacts/build_artifact_csharp.sh'], diff --git a/tools/run_tests/dockerize/build_docker_and_run_tests.sh b/tools/run_tests/dockerize/build_docker_and_run_tests.sh index f10916d19235f1284287e9f5111ec76fcc419072..79287454c93d52e4bdda4dd076e35578403e01fd 100755 --- a/tools/run_tests/dockerize/build_docker_and_run_tests.sh +++ b/tools/run_tests/dockerize/build_docker_and_run_tests.sh @@ -79,7 +79,11 @@ docker run \ -e HOST_GIT_ROOT=$git_root \ -e LOCAL_GIT_ROOT=$docker_instance_git_root \ -e "BUILD_ID=$BUILD_ID" \ + -e "BUILD_URL=$BUILD_URL" \ + -e "JOB_BASE_NAME=$JOB_BASE_NAME" \ -i $TTY_FLAG \ + --sysctl net.ipv6.conf.all.disable_ipv6=0 \ + -v ~/.config/gcloud:/root/.config/gcloud \ -v "$git_root:$docker_instance_git_root" \ -v /tmp/ccache:/tmp/ccache \ -v /tmp/npm-cache:/tmp/npm-cache \ diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 15268777d608941e33be5ffcbc12eb3e2f259c70..8a5a2887cccf04923cfcd2ae17fcf19a280f870f 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -232,6 +232,21 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "check_epollexclusive", + "src": [ + "test/build/check_epollexclusive.c" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -463,9 +478,9 @@ "headers": [], "is_filegroup": false, "language": "c", - "name": "ev_epoll_linux_test", + "name": "ev_epollsig_linux_test", "src": [ - "test/core/iomgr/ev_epoll_linux_test.c" + "test/core/iomgr/ev_epollsig_linux_test.c" ], "third_party": false, "type": "target" @@ -7427,6 +7442,7 @@ "test/core/end2end/tests/simple_request.c", "test/core/end2end/tests/streaming_error_response.c", "test/core/end2end/tests/trailing_metadata.c", + "test/core/end2end/tests/workaround_cronet_compression.c", "test/core/end2end/tests/write_buffering.c", "test/core/end2end/tests/write_buffering_at_end.c" ], @@ -7502,6 +7518,7 @@ "test/core/end2end/tests/simple_request.c", "test/core/end2end/tests/streaming_error_response.c", "test/core/end2end/tests/trailing_metadata.c", + "test/core/end2end/tests/workaround_cronet_compression.c", "test/core/end2end/tests/write_buffering.c", "test/core/end2end/tests/write_buffering_at_end.c" ], @@ -7759,7 +7776,8 @@ { "deps": [ "gpr", - "grpc_codegen" + "grpc_codegen", + "grpc_trace" ], "headers": [ "include/grpc/byte_buffer.h", @@ -7782,7 +7800,6 @@ "src/core/lib/channel/handshaker_registry.h", "src/core/lib/compression/algorithm_metadata.h", "src/core/lib/compression/message_compress.h", - "src/core/lib/debug/trace.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", "src/core/lib/http/parser.h", @@ -7792,7 +7809,11 @@ "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/error_internal.h", - "src/core/lib/iomgr/ev_epoll_linux.h", + "src/core/lib/iomgr/ev_epoll1_linux.h", + "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h", + "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h", + "src/core/lib/iomgr/ev_epollex_linux.h", + "src/core/lib/iomgr/ev_epollsig_linux.h", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.h", "src/core/lib/iomgr/exec_ctx.h", @@ -7801,6 +7822,7 @@ "src/core/lib/iomgr/iomgr.h", "src/core/lib/iomgr/iomgr_internal.h", "src/core/lib/iomgr/iomgr_posix.h", + "src/core/lib/iomgr/is_epollexclusive_available.h", "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/network_status_tracker.h", @@ -7822,6 +7844,7 @@ "src/core/lib/iomgr/socket_utils.h", "src/core/lib/iomgr/socket_utils_posix.h", "src/core/lib/iomgr/socket_windows.h", + "src/core/lib/iomgr/sys_epoll_wrapper.h", "src/core/lib/iomgr/tcp_client.h", "src/core/lib/iomgr/tcp_client_posix.h", "src/core/lib/iomgr/tcp_posix.h", @@ -7833,6 +7856,7 @@ "src/core/lib/iomgr/timer.h", "src/core/lib/iomgr/timer_generic.h", "src/core/lib/iomgr/timer_heap.h", + "src/core/lib/iomgr/timer_manager.h", "src/core/lib/iomgr/timer_uv.h", "src/core/lib/iomgr/udp_server.h", "src/core/lib/iomgr/unix_sockets_posix.h", @@ -7912,8 +7936,6 @@ "src/core/lib/compression/compression.c", "src/core/lib/compression/message_compress.c", "src/core/lib/compression/message_compress.h", - "src/core/lib/debug/trace.c", - "src/core/lib/debug/trace.h", "src/core/lib/http/format_request.c", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.c", @@ -7933,8 +7955,16 @@ "src/core/lib/iomgr/error.c", "src/core/lib/iomgr/error.h", "src/core/lib/iomgr/error_internal.h", - "src/core/lib/iomgr/ev_epoll_linux.c", - "src/core/lib/iomgr/ev_epoll_linux.h", + "src/core/lib/iomgr/ev_epoll1_linux.c", + "src/core/lib/iomgr/ev_epoll1_linux.h", + "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c", + "src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h", + "src/core/lib/iomgr/ev_epoll_thread_pool_linux.c", + "src/core/lib/iomgr/ev_epoll_thread_pool_linux.h", + "src/core/lib/iomgr/ev_epollex_linux.c", + "src/core/lib/iomgr/ev_epollex_linux.h", + "src/core/lib/iomgr/ev_epollsig_linux.c", + "src/core/lib/iomgr/ev_epollsig_linux.h", "src/core/lib/iomgr/ev_poll_posix.c", "src/core/lib/iomgr/ev_poll_posix.h", "src/core/lib/iomgr/ev_posix.c", @@ -7952,6 +7982,8 @@ "src/core/lib/iomgr/iomgr_posix.h", "src/core/lib/iomgr/iomgr_uv.c", "src/core/lib/iomgr/iomgr_windows.c", + "src/core/lib/iomgr/is_epollexclusive_available.c", + "src/core/lib/iomgr/is_epollexclusive_available.h", "src/core/lib/iomgr/load_file.c", "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.c", @@ -7994,6 +8026,7 @@ "src/core/lib/iomgr/socket_utils_windows.c", "src/core/lib/iomgr/socket_windows.c", "src/core/lib/iomgr/socket_windows.h", + "src/core/lib/iomgr/sys_epoll_wrapper.h", "src/core/lib/iomgr/tcp_client.h", "src/core/lib/iomgr/tcp_client_posix.c", "src/core/lib/iomgr/tcp_client_posix.h", @@ -8020,6 +8053,8 @@ "src/core/lib/iomgr/timer_generic.h", "src/core/lib/iomgr/timer_heap.c", "src/core/lib/iomgr/timer_heap.h", + "src/core/lib/iomgr/timer_manager.c", + "src/core/lib/iomgr/timer_manager.h", "src/core/lib/iomgr/timer_uv.c", "src/core/lib/iomgr/timer_uv.h", "src/core/lib/iomgr/udp_server.c", @@ -8642,6 +8677,23 @@ "third_party": false, "type": "filegroup" }, + { + "deps": [ + "gpr" + ], + "headers": [ + "src/core/lib/debug/trace.h" + ], + "is_filegroup": true, + "language": "c", + "name": "grpc_trace", + "src": [ + "src/core/lib/debug/trace.c", + "src/core/lib/debug/trace.h" + ], + "third_party": false, + "type": "filegroup" + }, { "deps": [ "gpr", @@ -8912,7 +8964,8 @@ }, { "deps": [ - "gpr" + "gpr", + "grpc_trace" ], "headers": [ "src/core/tsi/fake_transport_security.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 30a6b9bff452afccc723e0e7b2fd09dc120ceb92..2c8e4ebae7a2e0d13f78e16de4f111a92a18ffc5 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -572,7 +572,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "ev_epoll_linux_test", + "name": "ev_epollsig_linux_test", "platforms": [ "linux" ] @@ -4205,7 +4205,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4229,7 +4230,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4253,7 +4255,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4277,7 +4280,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4303,7 +4307,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4327,7 +4332,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4351,7 +4357,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4378,7 +4385,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4405,7 +4413,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4432,7 +4441,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4459,7 +4469,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4486,7 +4497,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4513,7 +4525,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4540,7 +4553,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4567,7 +4581,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4594,7 +4609,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4621,7 +4637,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4648,7 +4665,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4675,7 +4693,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4702,7 +4721,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4729,7 +4749,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4756,7 +4777,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4783,7 +4805,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4810,7 +4833,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4837,7 +4861,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4864,7 +4889,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4891,7 +4917,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4917,7 +4944,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4941,7 +4969,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4965,7 +4994,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -4991,7 +5021,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5015,7 +5046,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5039,7 +5071,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5063,7 +5096,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5087,7 +5121,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5111,7 +5146,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5135,7 +5171,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5159,7 +5196,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5185,7 +5223,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5211,7 +5250,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5235,7 +5275,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5261,7 +5302,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5285,7 +5327,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5309,7 +5352,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5335,7 +5379,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5359,7 +5404,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5383,7 +5429,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5409,7 +5456,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5433,7 +5481,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5457,7 +5506,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5481,7 +5531,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5505,7 +5556,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5531,7 +5583,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5555,7 +5608,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5579,7 +5633,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5603,7 +5658,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5629,7 +5685,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5653,7 +5710,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5677,7 +5735,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5701,7 +5760,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5725,7 +5785,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5749,7 +5810,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5773,7 +5835,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5797,7 +5860,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -5821,7 +5885,8 @@ "cpu_cost": 1.0, "defaults": "boringssl", "exclude_configs": [ - "asan" + "asan", + "ubsan" ], "flaky": false, "language": "c++", @@ -7010,6 +7075,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -8210,6 +8298,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -9382,6 +9493,28 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_fakesec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -10438,6 +10571,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -11661,6 +11817,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -12676,6 +12855,25 @@ "linux" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_test", + "platforms": [ + "linux" + ] + }, { "args": [ "write_buffering" @@ -13845,6 +14043,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -15068,6 +15289,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+workarounds_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -16338,6 +16582,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -17563,6 +17831,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -18833,6 +19124,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_oauth2_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -19865,6 +20180,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -20969,6 +21308,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -22003,14 +22366,14 @@ }, { "args": [ - "write_buffering" + "workaround_cronet_compression" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -22027,7 +22390,7 @@ }, { "args": [ - "write_buffering_at_end" + "write_buffering" ], "ci_platforms": [ "windows", @@ -22051,59 +22414,7 @@ }, { "args": [ - "authority_not_supported" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "bad_hostname" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "binary_metadata" + "write_buffering_at_end" ], "ci_platforms": [ "windows", @@ -22111,15 +22422,13 @@ "posix" ], "cpu_cost": 0.1, - "exclude_configs": [ - "msan" - ], + "exclude_configs": [], "exclude_iomgrs": [ "uv" ], "flaky": false, "language": "c", - "name": "h2_sockpair_1byte_test", + "name": "h2_sockpair+trace_test", "platforms": [ "windows", "linux", @@ -22129,7 +22438,7 @@ }, { "args": [ - "call_creds" + "authority_not_supported" ], "ci_platforms": [ "windows", @@ -22155,40 +22464,14 @@ }, { "args": [ - "cancel_after_accept" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 0.1, - "exclude_configs": [ - "msan" - ], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_1byte_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "cancel_after_client_done" + "bad_hostname" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [ "msan" ], @@ -22207,7 +22490,111 @@ }, { "args": [ - "cancel_after_invoke" + "binary_metadata" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "call_creds" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_accept" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_client_done" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "cancel_after_invoke" ], "ci_platforms": [ "windows", @@ -23167,6 +23554,32 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -24396,6 +24809,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -25619,6 +26055,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_ssl_cert_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -26649,6 +27108,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_ssl_proxy_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -27847,6 +28330,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -29047,6 +29553,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_census_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -30224,6 +30753,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_compress_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -31259,6 +31811,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_fd_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -32459,6 +33034,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -33455,6 +34053,25 @@ "linux" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_full+pipe_nosec_test", + "platforms": [ + "linux" + ] + }, { "args": [ "write_buffering" @@ -34601,6 +35218,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -35801,6 +36441,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_full+workarounds_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -37047,6 +37710,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_http_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -38249,6 +38936,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "language": "c", + "name": "h2_load_reporting_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -39255,6 +39965,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_proxy_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -39929,14 +40663,62 @@ }, { "args": [ - "network_status_change" + "network_status_change" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 0.1, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "no_logging" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, + { + "args": [ + "no_op" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -39953,7 +40735,7 @@ }, { "args": [ - "no_logging" + "payload" ], "ci_platforms": [ "windows", @@ -39977,14 +40759,14 @@ }, { "args": [ - "no_op" + "ping_pong_streaming" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -40001,7 +40783,7 @@ }, { "args": [ - "payload" + "registered_call" ], "ci_platforms": [ "windows", @@ -40025,7 +40807,7 @@ }, { "args": [ - "ping_pong_streaming" + "request_with_flags" ], "ci_platforms": [ "windows", @@ -40049,31 +40831,7 @@ }, { "args": [ - "registered_call" - ], - "ci_platforms": [ - "windows", - "linux", - "posix" - ], - "cpu_cost": 1.0, - "exclude_configs": [], - "exclude_iomgrs": [ - "uv" - ], - "flaky": false, - "language": "c", - "name": "h2_sockpair_nosec_test", - "platforms": [ - "windows", - "linux", - "mac", - "posix" - ] - }, - { - "args": [ - "request_with_flags" + "request_with_payload" ], "ci_platforms": [ "windows", @@ -40097,14 +40855,14 @@ }, { "args": [ - "request_with_payload" + "resource_quota_server" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -40121,14 +40879,14 @@ }, { "args": [ - "resource_quota_server" + "server_finishes_request" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -40145,7 +40903,7 @@ }, { "args": [ - "server_finishes_request" + "shutdown_finishes_calls" ], "ci_platforms": [ "windows", @@ -40169,7 +40927,7 @@ }, { "args": [ - "shutdown_finishes_calls" + "shutdown_finishes_tags" ], "ci_platforms": [ "windows", @@ -40193,7 +40951,7 @@ }, { "args": [ - "shutdown_finishes_tags" + "simple_cacheable_request" ], "ci_platforms": [ "windows", @@ -40217,14 +40975,14 @@ }, { "args": [ - "simple_cacheable_request" + "simple_metadata" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -40241,7 +40999,7 @@ }, { "args": [ - "simple_metadata" + "simple_request" ], "ci_platforms": [ "windows", @@ -40265,14 +41023,14 @@ }, { "args": [ - "simple_request" + "streaming_error_response" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 1.0, + "cpu_cost": 0.1, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -40289,14 +41047,14 @@ }, { "args": [ - "streaming_error_response" + "trailing_metadata" ], "ci_platforms": [ "windows", "linux", "posix" ], - "cpu_cost": 0.1, + "cpu_cost": 1.0, "exclude_configs": [], "exclude_iomgrs": [ "uv" @@ -40313,7 +41071,7 @@ }, { "args": [ - "trailing_metadata" + "workaround_cronet_compression" ], "ci_platforms": [ "windows", @@ -41343,6 +42101,30 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair+trace_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -42483,6 +43265,32 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "windows", + "linux", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [ + "msan" + ], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_sockpair_1byte_nosec_test", + "platforms": [ + "windows", + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -43662,6 +44470,29 @@ "posix" ] }, + { + "args": [ + "workaround_cronet_compression" + ], + "ci_platforms": [ + "linux", + "mac", + "posix" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "language": "c", + "name": "h2_uds_nosec_test", + "platforms": [ + "linux", + "mac", + "posix" + ] + }, { "args": [ "write_buffering" @@ -43708,6 +44539,56 @@ "posix" ] }, + { + "args": [ + "--scenarios_json", + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + ], + "boringssl": true, + "ci_platforms": [ + "linux" + ], + "cpu_cost": "capacity", + "defaults": "boringssl", + "exclude_configs": [ + "tsan", + "asan" + ], + "excluded_poll_engines": [], + "flaky": false, + "language": "c++", + "name": "json_run_localhost", + "platforms": [ + "linux" + ], + "shortname": "json_run_localhost:cpp_protobuf_async_unary_1channel_100rpcs_1MB", + "timeout_seconds": 360 + }, + { + "args": [ + "--scenarios_json", + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + ], + "boringssl": true, + "ci_platforms": [ + "linux" + ], + "cpu_cost": "capacity", + "defaults": "boringssl", + "exclude_configs": [ + "tsan", + "asan" + ], + "excluded_poll_engines": [], + "flaky": false, + "language": "c++", + "name": "json_run_localhost", + "platforms": [ + "linux" + ], + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_1channel_1MB", + "timeout_seconds": 360 + }, { "args": [ "--scenarios_json", @@ -43861,7 +44742,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -44640,7 +45521,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -45266,6 +46147,82 @@ "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_server_qps_unconstrained_insecure", "timeout_seconds": 360 }, + { + "args": [ + "--scenarios_json", + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_unary_1channel_100rpcs_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"UNARY\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + ], + "boringssl": true, + "ci_platforms": [ + "linux" + ], + "cpu_cost": "capacity", + "defaults": "boringssl", + "exclude_configs": [ + "asan-noleaks", + "asan-trace-cmp", + "basicprof", + "c++-compat", + "counters", + "dbg", + "gcov", + "helgrind", + "lto", + "memcheck", + "msan", + "mutrace", + "opt", + "stapprof", + "ubsan" + ], + "excluded_poll_engines": [], + "flaky": false, + "language": "c++", + "name": "json_run_localhost", + "platforms": [ + "linux" + ], + "shortname": "json_run_localhost:cpp_protobuf_async_unary_1channel_100rpcs_1MB_low_thread_count", + "timeout_seconds": 360 + }, + { + "args": [ + "--scenarios_json", + "{\"scenarios\": [{\"name\": \"cpp_protobuf_async_streaming_from_client_1channel_1MB\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 0, \"security_params\": null, \"server_type\": \"ASYNC_SERVER\"}, \"num_clients\": 1, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"simple_params\": {\"resp_size\": 1048576, \"req_size\": 1048576}}, \"client_channels\": 1, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 1, \"rpc_type\": \"STREAMING_FROM_CLIENT\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + ], + "boringssl": true, + "ci_platforms": [ + "linux" + ], + "cpu_cost": "capacity", + "defaults": "boringssl", + "exclude_configs": [ + "asan-noleaks", + "asan-trace-cmp", + "basicprof", + "c++-compat", + "counters", + "dbg", + "gcov", + "helgrind", + "lto", + "memcheck", + "msan", + "mutrace", + "opt", + "stapprof", + "ubsan" + ], + "excluded_poll_engines": [], + "flaky": false, + "language": "c++", + "name": "json_run_localhost", + "platforms": [ + "linux" + ], + "shortname": "json_run_localhost:cpp_protobuf_async_streaming_from_client_1channel_1MB_low_thread_count", + "timeout_seconds": 360 + }, { "args": [ "--scenarios_json", @@ -45497,7 +46454,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_secure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": {\"use_test_ca\": true, \"server_host_override\": \"foo.test.google.fr\"}, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ @@ -46679,7 +47636,7 @@ { "args": [ "--scenarios_json", - "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 100, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" + "{\"scenarios\": [{\"name\": \"cpp_generic_async_streaming_qps_one_server_core_insecure\", \"warmup_seconds\": 0, \"benchmark_seconds\": 1, \"num_servers\": 1, \"server_config\": {\"async_server_threads\": 1, \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"server_type\": \"ASYNC_GENERIC_SERVER\"}, \"num_clients\": 0, \"client_config\": {\"client_type\": \"ASYNC_CLIENT\", \"security_params\": null, \"payload_config\": {\"bytebuf_params\": {\"resp_size\": 0, \"req_size\": 0}}, \"client_channels\": 64, \"async_client_threads\": 0, \"outstanding_rpcs_per_channel\": 13, \"rpc_type\": \"STREAMING\", \"load_params\": {\"closed_loop\": {}}, \"histogram_params\": {\"max_possible\": 60000000000.0, \"resolution\": 0.01}}}]}" ], "boringssl": true, "ci_platforms": [ diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py index 459120d647fac7a1c860d67be9184fdaf2c70629..c2ffd67dbf4c8a4d0ca30ab73e278d46a23e3786 100644 --- a/tools/run_tests/performance/scenario_config.py +++ b/tools/run_tests/performance/scenario_config.py @@ -53,6 +53,7 @@ HISTOGRAM_PARAMS = { # actual target will be slightly higher) OUTSTANDING_REQUESTS={ 'async': 6400, + 'async-1core': 800, 'sync': 1000 } @@ -111,6 +112,7 @@ def _ping_pong_scenario(name, rpc_type, categories=DEFAULT_CATEGORIES, channels=None, outstanding=None, + num_clients=None, resource_quota_size=None, messages_per_stream=None, excluded_poll_engines=[]): @@ -157,7 +159,7 @@ def _ping_pong_scenario(name, rpc_type, wide = channels if channels is not None else WIDE deep = int(math.ceil(1.0 * outstanding_calls / wide)) - scenario['num_clients'] = 0 # use as many client as available. + scenario['num_clients'] = num_clients if num_clients is not None else 0 # use as many clients as available. scenario['client_config']['outstanding_rpcs_per_channel'] = deep scenario['client_config']['client_channels'] = wide scenario['client_config']['async_client_threads'] = 0 @@ -195,6 +197,24 @@ class CXXLanguage: def scenarios(self): # TODO(ctiller): add 70% load latency test + yield _ping_pong_scenario( + 'cpp_protobuf_async_unary_1channel_100rpcs_1MB', rpc_type='UNARY', + client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', + req_size=1024*1024, resp_size=1024*1024, + unconstrained_client='async', outstanding=100, channels=1, + num_clients=1, + secure=False, + categories=[SMOKETEST] + [SCALABLE]) + + yield _ping_pong_scenario( + 'cpp_protobuf_async_streaming_from_client_1channel_1MB', rpc_type='STREAMING_FROM_CLIENT', + client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER', + req_size=1024*1024, resp_size=1024*1024, + unconstrained_client='async', outstanding=1, channels=1, + num_clients=1, + secure=False, + categories=[SMOKETEST] + [SCALABLE]) + for secure in [True, False]: secstr = 'secure' if secure else 'insecure' smoketest_categories = ([SMOKETEST] if secure else []) + [SCALABLE] @@ -265,7 +285,7 @@ class CXXLanguage: rpc_type='STREAMING', client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', - unconstrained_client='async', use_generic_payload=True, + unconstrained_client='async-1core', use_generic_payload=True, async_server_threads=1, secure=secure) @@ -752,7 +772,7 @@ class JavaLanguage: yield _ping_pong_scenario( 'java_generic_async_streaming_qps_one_server_core_%s' % secstr, rpc_type='STREAMING', client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', - unconstrained_client='async', use_generic_payload=True, + unconstrained_client='async-1core', use_generic_payload=True, async_server_threads=1, secure=secure, warmup_seconds=JAVA_WARMUP_SECONDS) diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py index d01e82a76b18ea7587af7844838cf56b7eba3166..c1b1c88f550ac672719d6cb236401260620a1351 100755 --- a/tools/run_tests/python_utils/jobset.py +++ b/tools/run_tests/python_utils/jobset.py @@ -222,7 +222,8 @@ class JobResult(object): self.num_failures = 0 self.retries = 0 self.message = '' - + self.cpu_estimated = 1 + self.cpu_measured = 0 class Job(object): """Manages one job.""" @@ -254,7 +255,7 @@ class Job(object): self._start = time.time() cmdline = self._spec.cmdline if measure_cpu_costs: - cmdline = ['time', '--portability'] + cmdline + cmdline = ['time', '-p'] + cmdline try_start = lambda: subprocess.Popen(args=cmdline, stderr=subprocess.STDOUT, stdout=self._tempfile, @@ -306,13 +307,15 @@ class Job(object): self._state = _SUCCESS measurement = '' if measure_cpu_costs: - m = re.search(r'real ([0-9.]+)\nuser ([0-9.]+)\nsys ([0-9.]+)', stdout()) + m = re.search(r'real\s+([0-9.]+)\nuser\s+([0-9.]+)\nsys\s+([0-9.]+)', stdout()) real = float(m.group(1)) user = float(m.group(2)) sys = float(m.group(3)) if real > 0.5: cores = (user + sys) / real - measurement = '; cpu_cost=%.01f; estimated=%.01f' % (cores, self._spec.cpu_cost) + self.result.cpu_measured = float('%.01f' % cores) + self.result.cpu_estimated = float('%.01f' % self._spec.cpu_cost) + measurement = '; cpu_cost=%.01f; estimated=%.01f' % (self.result.cpu_measured, self.result.cpu_estimated) if not self._quiet_success: message('PASSED', '%s [time=%.1fsec; retries=%d:%d%s]' % ( self._spec.shortname, elapsed, self._retries, self._timeout_retries, measurement), diff --git a/tools/run_tests/python_utils/port_server.py b/tools/run_tests/python_utils/port_server.py index 079ed70fbf3152c2a859cf44d60cc2088f94ded8..9860b928081f027cc661e3819f1cd515083ccb28 100755 --- a/tools/run_tests/python_utils/port_server.py +++ b/tools/run_tests/python_utils/port_server.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2.7 # Copyright 2015, Google Inc. # All rights reserved. # @@ -30,8 +30,6 @@ """Manage TCP ports for unit tests; started by run_tests.py""" -from __future__ import print_function - import argparse from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler import hashlib @@ -42,16 +40,17 @@ import time import random from SocketServer import ThreadingMixIn import threading +import platform # increment this number whenever making a change to ensure that # the changes are picked up by running CI servers # note that all changes must be backwards compatible -_MY_VERSION = 19 +_MY_VERSION = 20 if len(sys.argv) == 2 and sys.argv[1] == 'dump_version': - print(_MY_VERSION) + print _MY_VERSION sys.exit(0) @@ -67,13 +66,16 @@ if args.logfile is not None: sys.stderr = open(args.logfile, 'w') sys.stdout = sys.stderr -print('port server running on port %d' % args.port) +print 'port server running on port %d' % args.port pool = [] in_use = {} mu = threading.Lock() def can_connect(port): + # this test is only really useful on unices where SO_REUSE_PORT is available + # so on Windows, where this test is expensive, skip it + if platform.system() == 'Windows': return False s = socket.socket() try: s.connect(('localhost', port)) @@ -137,7 +139,7 @@ keep_running = True class Handler(BaseHTTPRequestHandler): - + def setup(self): # If the client is unreachable for 5 seconds, close the connection self.timeout = 5 @@ -195,6 +197,4 @@ class Handler(BaseHTTPRequestHandler): class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): """Handle requests in a separate thread""" - ThreadedHTTPServer(('', args.port), Handler).serve_forever() - diff --git a/tools/run_tests/python_utils/report_utils.py b/tools/run_tests/python_utils/report_utils.py index 502efc31f4fef77293f5af0d82bb9654260476fc..b8dd67e06048f9ac4e464d2366da887938573781 100644 --- a/tools/run_tests/python_utils/report_utils.py +++ b/tools/run_tests/python_utils/report_utils.py @@ -89,6 +89,7 @@ def render_junit_xml_report(resultset, xml_report, suite_package='grpc', tree = ET.ElementTree(root) tree.write(xml_report, encoding='UTF-8') + def render_interop_html_report( client_langs, server_langs, test_cases, auth_test_cases, http2_cases, http2_server_cases, resultset, diff --git a/tools/run_tests/python_utils/start_port_server.py b/tools/run_tests/python_utils/start_port_server.py index deb7354438806d621b29701f7fdf57b4715cb299..4acc964c7b15670dc680d0a6c774bf2d707b0c56 100644 --- a/tools/run_tests/python_utils/start_port_server.py +++ b/tools/run_tests/python_utils/start_port_server.py @@ -27,9 +27,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from __future__ import print_function - -from six.moves import urllib +import urllib import jobset import logging import os @@ -50,9 +48,9 @@ def start_port_server(): # otherwise, leave it up try: version = int( - urllib.request.urlopen( - 'http://localhost:%d/version_number' % _PORT_SERVER_PORT, - timeout=10).read()) + urllib.urlopen( + 'http://localhost:%d/version_number' % + _PORT_SERVER_PORT).read()) logging.info('detected port server running version %d', version) running = True except Exception as e: @@ -69,8 +67,8 @@ def start_port_server(): running = (version >= current_version) if not running: logging.info('port_server version mismatch: killing the old one') - urllib.request.urlopen('http://localhost:%d/quitquitquit' % - _PORT_SERVER_PORT).read() + urllib.urlopen('http://localhost:%d/quitquitquit' % + _PORT_SERVER_PORT).read() time.sleep(1) if not running: fd, logfile = tempfile.mkstemp() @@ -109,9 +107,8 @@ def start_port_server(): # try one final time: maybe another build managed to start one time.sleep(1) try: - urllib.request.urlopen( - 'http://localhost:%d/get' % _PORT_SERVER_PORT, - timeout=1).read() + urllib.urlopen( + 'http://localhost:%d/get' % _PORT_SERVER_PORT).read() logging.info( 'last ditch attempt to contact port server succeeded') break @@ -119,18 +116,18 @@ def start_port_server(): logging.exception( 'final attempt to contact port server failed') port_log = open(logfile, 'r').read() - print(port_log) + print port_log sys.exit(1) try: port_server_url = 'http://localhost:%d/get' % _PORT_SERVER_PORT - urllib.request.urlopen(port_server_url, timeout=1).read() + urllib.urlopen(port_server_url).read() logging.info('port server is up and ready') break except socket.timeout: logging.exception('while waiting for port_server') time.sleep(1) waits += 1 - except urllib.error.URLError: + except IOError: logging.exception('while waiting for port_server') time.sleep(1) waits += 1 diff --git a/tools/run_tests/python_utils/upload_test_results.py b/tools/run_tests/python_utils/upload_test_results.py new file mode 100644 index 0000000000000000000000000000000000000000..d076d1e5a2a1683ac0d613f3271cd7b83a01a795 --- /dev/null +++ b/tools/run_tests/python_utils/upload_test_results.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# Copyright 2017, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Helper to upload Jenkins test results to BQ""" + +from __future__ import print_function + +import os +import six +import sys +import time +import uuid + +gcp_utils_dir = os.path.abspath(os.path.join( + os.path.dirname(__file__), '../../gcp/utils')) +sys.path.append(gcp_utils_dir) +import big_query_utils + +_DATASET_ID = 'jenkins_test_results' +_DESCRIPTION = 'Test results from master job run on Jenkins' +_PROJECT_ID = 'grpc-testing' +_RESULTS_SCHEMA = [ + ('job_name', 'STRING', 'Name of Jenkins job'), + ('build_id', 'INTEGER', 'Build ID of Jenkins job'), + ('build_url', 'STRING', 'URL of Jenkins job'), + ('test_name', 'STRING', 'Individual test name'), + ('language', 'STRING', 'Language of test'), + ('platform', 'STRING', 'Platform used for test'), + ('config', 'STRING', 'Config used for test'), + ('compiler', 'STRING', 'Compiler used for test'), + ('iomgr_platform', 'STRING', 'Iomgr used for test'), + ('result', 'STRING', 'Test result: PASSED, TIMEOUT, FAILED, or SKIPPED'), + ('timestamp', 'TIMESTAMP', 'Timestamp of test run'), + ('elapsed_time', 'FLOAT', 'How long test took to run'), + ('cpu_estimated', 'FLOAT', 'Estimated CPU usage of test'), + ('cpu_measured', 'FLOAT', 'Actual CPU usage of test'), +] + + +def _get_build_metadata(test_results): + """Add Jenkins build metadata to test_results based on environment variables set by Jenkins.""" + build_id = os.getenv('BUILD_ID') + build_url = os.getenv('BUILD_URL') + job_name = os.getenv('JOB_BASE_NAME') + + if build_id: + test_results['build_id'] = build_id + if build_url: + test_results['build_url'] = build_url + if job_name: + test_results['job_name'] = job_name + +def upload_results_to_bq(resultset, bq_table, args, platform): + """Upload test results to a BQ table. + + Args: + resultset: dictionary generated by jobset.run + bq_table: string name of table to create/upload results to in BQ + args: args in run_tests.py, generated by argparse + platform: string name of platform tests were run on + """ + bq = big_query_utils.create_big_query() + big_query_utils.create_table(bq, _PROJECT_ID, _DATASET_ID, bq_table, _RESULTS_SCHEMA, _DESCRIPTION) + + for shortname, results in six.iteritems(resultset): + for result in results: + test_results = {} + _get_build_metadata(test_results) + test_results['compiler'] = args.compiler + test_results['config'] = args.config + test_results['cpu_estimated'] = result.cpu_estimated + test_results['cpu_measured'] = result.cpu_measured + test_results['elapsed_time'] = '%.2f' % result.elapsed_time + test_results['iomgr_platform'] = args.iomgr_platform + # args.language is a list, but will always have one element in the contexts + # this function is used. + test_results['language'] = args.language[0] + test_results['platform'] = platform + test_results['result'] = result.state + test_results['test_name'] = shortname + test_results['timestamp'] = time.strftime('%Y-%m-%d %H:%M:%S') + + row = big_query_utils.make_row(str(uuid.uuid4()), test_results) + if not big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET_ID, bq_table, [row]): + print('Error uploading result to bigquery.') + sys.exit(1) diff --git a/tools/run_tests/run_stress_tests.py b/tools/run_tests/run_stress_tests.py deleted file mode 100755 index 4eea02118e54682f5c6e26b36f53c7fdaa11966f..0000000000000000000000000000000000000000 --- a/tools/run_tests/run_stress_tests.py +++ /dev/null @@ -1,331 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Run stress test in C++""" - -from __future__ import print_function - -import argparse -import atexit -import itertools -import json -import multiprocessing -import os -import re -import subprocess -import sys -import tempfile -import time -import uuid -import six - -import python_utils.dockerjob as dockerjob -import python_utils.jobset as jobset - -# Docker doesn't clean up after itself, so we do it on exit. -atexit.register(lambda: subprocess.call(['stty', 'echo'])) - -ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..')) -os.chdir(ROOT) - -_DEFAULT_SERVER_PORT = 8080 -_DEFAULT_METRICS_PORT = 8081 -_DEFAULT_TEST_CASES = 'empty_unary:20,large_unary:20,client_streaming:20,server_streaming:20,empty_stream:20' -_DEFAULT_NUM_CHANNELS_PER_SERVER = 5 -_DEFAULT_NUM_STUBS_PER_CHANNEL = 10 - -# 15 mins default -_DEFAULT_TEST_DURATION_SECS = 900 - -class CXXLanguage: - - def __init__(self): - self.client_cwd = None - self.server_cwd = None - self.safename = 'cxx' - - def client_cmd(self, args): - return ['bins/opt/stress_test'] + args - - def server_cmd(self, args): - return ['bins/opt/interop_server'] + args - - def global_env(self): - return {} - - def __str__(self): - return 'c++' - - -_LANGUAGES = {'c++': CXXLanguage(),} - -# languages supported as cloud_to_cloud servers -_SERVERS = ['c++'] - -DOCKER_WORKDIR_ROOT = '/var/local/git/grpc' - - -def docker_run_cmdline(cmdline, image, docker_args=[], cwd=None, environ=None): - """Wraps given cmdline array to create 'docker run' cmdline from it.""" - docker_cmdline = ['docker', 'run', '-i', '--rm=true'] - - # turn environ into -e docker args - if environ: - for k, v in environ.items(): - docker_cmdline += ['-e', '%s=%s' % (k, v)] - - # set working directory - workdir = DOCKER_WORKDIR_ROOT - if cwd: - workdir = os.path.join(workdir, cwd) - docker_cmdline += ['-w', workdir] - - docker_cmdline += docker_args + [image] + cmdline - return docker_cmdline - - -def bash_login_cmdline(cmdline): - """Creates bash -l -c cmdline from args list.""" - # Use login shell: - # * rvm and nvm require it - # * makes error messages clearer if executables are missing - return ['bash', '-l', '-c', ' '.join(cmdline)] - - -def _job_kill_handler(job): - if job._spec.container_name: - dockerjob.docker_kill(job._spec.container_name) - # When the job times out and we decide to kill it, - # we need to wait a before restarting the job - # to prevent "container name already in use" error. - # TODO(jtattermusch): figure out a cleaner way to to this. - time.sleep(2) - - -def cloud_to_cloud_jobspec(language, - test_cases, - server_addresses, - test_duration_secs, - num_channels_per_server, - num_stubs_per_channel, - metrics_port, - docker_image=None): - """Creates jobspec for cloud-to-cloud interop test""" - cmdline = bash_login_cmdline(language.client_cmd([ - '--test_cases=%s' % test_cases, '--server_addresses=%s' % - server_addresses, '--test_duration_secs=%s' % test_duration_secs, - '--num_stubs_per_channel=%s' % num_stubs_per_channel, - '--num_channels_per_server=%s' % num_channels_per_server, - '--metrics_port=%s' % metrics_port - ])) - print(cmdline) - cwd = language.client_cwd - environ = language.global_env() - if docker_image: - container_name = dockerjob.random_name('interop_client_%s' % - language.safename) - cmdline = docker_run_cmdline( - cmdline, - image=docker_image, - environ=environ, - cwd=cwd, - docker_args=['--net=host', '--name', container_name]) - cwd = None - - test_job = jobset.JobSpec(cmdline=cmdline, - cwd=cwd, - environ=environ, - shortname='cloud_to_cloud:%s:%s_server:stress_test' % ( - language, server_name), - timeout_seconds=test_duration_secs * 2, - flake_retries=0, - timeout_retries=0, - kill_handler=_job_kill_handler) - test_job.container_name = container_name - return test_job - - -def server_jobspec(language, docker_image, test_duration_secs): - """Create jobspec for running a server""" - container_name = dockerjob.random_name('interop_server_%s' % - language.safename) - cmdline = bash_login_cmdline(language.server_cmd(['--port=%s' % - _DEFAULT_SERVER_PORT])) - environ = language.global_env() - docker_cmdline = docker_run_cmdline( - cmdline, - image=docker_image, - cwd=language.server_cwd, - environ=environ, - docker_args=['-p', str(_DEFAULT_SERVER_PORT), '--name', container_name]) - - server_job = jobset.JobSpec(cmdline=docker_cmdline, - environ=environ, - shortname='interop_server_%s' % language, - timeout_seconds=test_duration_secs * 3) - server_job.container_name = container_name - return server_job - - -def build_interop_stress_image_jobspec(language, tag=None): - """Creates jobspec for building stress test docker image for a language""" - if not tag: - tag = 'grpc_interop_stress_%s:%s' % (language.safename, uuid.uuid4()) - env = {'INTEROP_IMAGE': tag, - 'BASE_NAME': 'grpc_interop_stress_%s' % language.safename} - build_job = jobset.JobSpec(cmdline=['tools/run_tests/dockerize/build_interop_stress_image.sh'], - environ=env, - shortname='build_docker_%s' % (language), - timeout_seconds=30 * 60) - build_job.tag = tag - return build_job - -argp = argparse.ArgumentParser(description='Run stress tests.') -argp.add_argument('-l', - '--language', - choices=['all'] + sorted(_LANGUAGES), - nargs='+', - default=['all'], - help='Clients to run.') -argp.add_argument('-j', '--jobs', default=multiprocessing.cpu_count(), type=int) -argp.add_argument( - '-s', - '--server', - choices=['all'] + sorted(_SERVERS), - action='append', - help='Run cloud_to_cloud servers in a separate docker ' + 'image.', - default=[]) -argp.add_argument( - '--override_server', - action='append', - type=lambda kv: kv.split('='), - help= - 'Use servername=HOST:PORT to explicitly specify a server. E.g. ' - 'csharp=localhost:50000', - default=[]) -argp.add_argument('--test_duration_secs', - help='The duration of the test in seconds', - default=_DEFAULT_TEST_DURATION_SECS) - -args = argp.parse_args() - -servers = set( - s - for s in itertools.chain.from_iterable(_SERVERS if x == 'all' else [x] - for x in args.server)) - -languages = set(_LANGUAGES[l] for l in itertools.chain.from_iterable( - six.iterkeys(_LANGUAGES) if x == 'all' else [x] for x in args.language)) - -docker_images = {} -# languages for which to build docker images -languages_to_build = set( - _LANGUAGES[k] - for k in set([str(l) for l in languages] + [s for s in servers])) -build_jobs = [] -for l in languages_to_build: - job = build_interop_stress_image_jobspec(l) - docker_images[str(l)] = job.tag - build_jobs.append(job) - -if build_jobs: - jobset.message('START', 'Building interop docker images.', do_newline=True) - num_failures, _ = jobset.run(build_jobs, - newline_on_success=True, - maxjobs=args.jobs) - if num_failures == 0: - jobset.message('SUCCESS', - 'All docker images built successfully.', - do_newline=True) - else: - jobset.message('FAILED', - 'Failed to build interop docker images.', - do_newline=True) - for image in six.itervalues(docker_images): - dockerjob.remove_image(image, skip_nonexistent=True) - sys.exit(1) - -# Start interop servers. -server_jobs = {} -server_addresses = {} -try: - for s in servers: - lang = str(s) - spec = server_jobspec(_LANGUAGES[lang], docker_images.get(lang), args.test_duration_secs) - job = dockerjob.DockerJob(spec) - server_jobs[lang] = job - server_addresses[lang] = ('localhost', - job.mapped_port(_DEFAULT_SERVER_PORT)) - - jobs = [] - - for server in args.override_server: - server_name = server[0] - (server_host, server_port) = server[1].split(':') - server_addresses[server_name] = (server_host, server_port) - - for server_name, server_address in server_addresses.items(): - (server_host, server_port) = server_address - for language in languages: - test_job = cloud_to_cloud_jobspec( - language, - _DEFAULT_TEST_CASES, - ('%s:%s' % (server_host, server_port)), - args.test_duration_secs, - _DEFAULT_NUM_CHANNELS_PER_SERVER, - _DEFAULT_NUM_STUBS_PER_CHANNEL, - _DEFAULT_METRICS_PORT, - docker_image=docker_images.get(str(language))) - jobs.append(test_job) - - if not jobs: - print('No jobs to run.') - for image in six.itervalues(docker_images): - dockerjob.remove_image(image, skip_nonexistent=True) - sys.exit(1) - - num_failures, resultset = jobset.run(jobs, - newline_on_success=True, - maxjobs=args.jobs) - if num_failures: - jobset.message('FAILED', 'Some tests failed', do_newline=True) - else: - jobset.message('SUCCESS', 'All tests passed', do_newline=True) - -finally: - # Check if servers are still running. - for server, job in server_jobs.items(): - if not job.is_running(): - print('Server "%s" has exited prematurely.' % server) - - dockerjob.finish_jobs([j for j in six.itervalues(server_jobs)]) - - for image in six.itervalues(docker_images): - print('Removing docker image %s' % image) - dockerjob.remove_image(image) diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 62e92c3d1dd0df8deda3696a6fc502642e347db1..196e26e1b6096ba5a36196eefee3dc9e685631bc 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -60,7 +60,10 @@ import python_utils.jobset as jobset import python_utils.report_utils as report_utils import python_utils.watch_dirs as watch_dirs import python_utils.start_port_server as start_port_server - +try: + from python_utils.upload_test_results import upload_results_to_bq +except (ImportError): + pass # It's ok to not import because this is only necessary to upload results to BQ. _ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../..')) os.chdir(_ROOT) @@ -72,7 +75,8 @@ _FORCE_ENVIRON_FOR_WRAPPERS = { _POLLING_STRATEGIES = { - 'linux': ['epoll', 'poll', 'poll-cv'] + 'linux': ['epollsig', 'poll', 'poll-cv'] +# TODO(ctiller, sreecha): enable epoll1, epollex, epoll-thread-pool } @@ -336,7 +340,8 @@ class CLanguage(object): if self.platform == 'windows': # don't build tools on windows just yet return ['buildtests_%s' % self.make_target] - return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target] + return ['buildtests_%s' % self.make_target, 'tools_%s' % self.make_target, + 'check_epollexclusive'] def make_options(self): return self._make_options; @@ -387,10 +392,6 @@ class CLanguage(object): if compiler == 'gcc4.9' or compiler == 'default': return ('jessie', []) - elif compiler == 'gcc4.4': - return ('wheezy', self._gcc_make_options(version_suffix='-4.4')) - elif compiler == 'gcc4.6': - return ('wheezy', self._gcc_make_options(version_suffix='-4.6')) elif compiler == 'gcc4.8': return ('jessie', self._gcc_make_options(version_suffix='-4.8')) elif compiler == 'gcc5.3': @@ -1185,7 +1186,7 @@ argp.add_argument('--build_only', default=False, action='store_const', const=True, - help='Perform all the build steps but dont run any tests.') + help='Perform all the build steps but don\'t run any tests.') argp.add_argument('--measure_cpu_costs', default=False, action='store_const', const=True, help='Measure the cpu costs of tests') argp.add_argument('--update_submodules', default=[], nargs='*', @@ -1200,11 +1201,16 @@ argp.add_argument('--quiet_success', default=False, action='store_const', const=True, - help='Dont print anything when a test passes. Passing tests also will not be reported in XML report. ' + + help='Don\'t print anything when a test passes. Passing tests also will not be reported in XML report. ' + 'Useful when running many iterations of each test (argument -n).') argp.add_argument('--force_default_poller', default=False, action='store_const', const=True, - help='Dont try to iterate over many polling strategies when they exist') + help='Don\'t try to iterate over many polling strategies when they exist') argp.add_argument('--max_time', default=-1, type=int, help='Maximum test runtime in seconds') +argp.add_argument('--bq_result_table', + default='', + type=str, + nargs='?', + help='Upload test results to a specified BQ table.') args = argp.parse_args() if args.force_default_poller: @@ -1427,6 +1433,14 @@ class BuildAndRunError(object): POST_TEST = object() +def _has_epollexclusive(): + try: + subprocess.check_call('bins/%s/check_epollexclusive' % args.config) + return True + except subprocess.CalledProcessError, e: + return False + + # returns a list of things that failed (or an empty list on success) def _build_and_run( check_cancelled, newline_on_success, xml_report=None, build_only=False): @@ -1444,6 +1458,10 @@ def _build_and_run( suite_name=args.report_suite_name) return [] + if not args.travis and not _has_epollexclusive() and 'epollex' in _POLLING_STRATEGIES[platform_string()]: + print('\n\nOmitting EPOLLEXCLUSIVE tests\n\n') + _POLLING_STRATEGIES[platform_string()].remove('epollex') + # start antagonists antagonists = [subprocess.Popen(['tools/run_tests/python_utils/antagonist.py']) for _ in range(0, args.antagonists)] @@ -1503,6 +1521,8 @@ def _build_and_run( finally: for antagonist in antagonists: antagonist.kill() + if args.bq_result_table and resultset: + upload_results_to_bq(resultset, args.bq_result_table, args, platform_string()) if xml_report and resultset: report_utils.render_junit_xml_report(resultset, xml_report, suite_name=args.report_suite_name) diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index 474b56b5de5f6dc5735226ab4285ae6dce2fa04f..84551d93948cfabde687618a2e3bd4690d5adae3 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -197,20 +197,9 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS) inner_jobs=inner_jobs) # portability C and C++ on x64 - for compiler in ['gcc4.4', 'gcc4.6', 'gcc5.3', 'gcc_musl', + for compiler in ['gcc4.8', 'gcc5.3', 'gcc_musl', 'clang3.5', 'clang3.6', 'clang3.7']: - test_jobs += _generate_jobs(languages=['c'], - configs=['dbg'], - platforms=['linux'], - arch='x64', - compiler=compiler, - labels=['portability'], - extra_args=extra_args, - inner_jobs=inner_jobs) - - for compiler in ['gcc4.8', 'gcc5.3', - 'clang3.5', 'clang3.6', 'clang3.7']: - test_jobs += _generate_jobs(languages=['c++'], + test_jobs += _generate_jobs(languages=['c', 'c++'], configs=['dbg'], platforms=['linux'], arch='x64', @@ -267,6 +256,15 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS) extra_args=extra_args, inner_jobs=inner_jobs) + test_jobs += _generate_jobs(languages=['python'], + configs=['dbg'], + platforms=['linux'], + arch='default', + compiler='python_alpine', + labels=['portability'], + extra_args=extra_args, + inner_jobs=inner_jobs) + test_jobs += _generate_jobs(languages=['csharp'], configs=['dbg'], platforms=['linux'], @@ -387,6 +385,11 @@ if __name__ == "__main__": const=True, help='Put reports into subdirectories to improve presentation of ' 'results by Internal CI.') + argp.add_argument('--bq_result_table', + default='', + type=str, + nargs='?', + help='Upload test results to a specified BQ table.') args = argp.parse_args() if args.internal_ci: @@ -403,6 +406,10 @@ if __name__ == "__main__": extra_args.append('--quiet_success') if args.max_time > 0: extra_args.extend(('--max_time', '%d' % args.max_time)) + if args.bq_result_table: + extra_args.append('--bq_result_table') + extra_args.append('%s' % args.bq_result_table) + extra_args.append('--measure_cpu_costs') all_jobs = _create_test_jobs(extra_args=extra_args, inner_jobs=args.inner_jobs) + \ _create_portability_test_jobs(extra_args=extra_args, inner_jobs=args.inner_jobs) diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh index 6be7a39d070f62fc459f55cfb7922b45938ccdc3..43d05212e875cae0177cb207443361b7c3526d07 100755 --- a/tools/run_tests/sanity/check_submodules.sh +++ b/tools/run_tests/sanity/check_submodules.sh @@ -46,7 +46,7 @@ cat << EOF | awk '{ print $1 }' | sort > $want_submodules 886e7d75368e3f4fab3f4d0d3584e4abfc557755 third_party/boringssl-with-bazel (version_for_cocoapods_7.0-857-g886e7d7) 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0) ec44c6c1675c25b9827aacd08c02433cccde7780 third_party/googletest (release-1.8.0) - 593e917c176b5bc5aafa57bf9f6030d749d91cd5 third_party/protobuf (v3.1.0-alpha-1-326-g593e917) + a6189acd18b00611c1dc7042299ad75486f08a1a third_party/protobuf (v3.3.0) cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11) 7691f773af79bf75a62d1863fd0f13ebf9dc51b1 third_party/cares/cares (1.12.0) EOF diff --git a/tools/run_tests/start_port_server.py b/tools/run_tests/start_port_server.py index bfd72222b660bf8c6708ab8e277ebe629b257d4d..f7c9f43665e70b1716704a00ec95092d86264630 100755 --- a/tools/run_tests/start_port_server.py +++ b/tools/run_tests/start_port_server.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2.7 # Copyright 2017, Google Inc. # All rights reserved. @@ -39,10 +39,8 @@ The path to this file is called out in test/core/util/port.c, and printed as an error message to users. """ -from __future__ import print_function - import python_utils.start_port_server as start_port_server start_port_server.start_port_server() -print("Port server started successfully") +print "Port server started successfully" diff --git a/tools/run_tests/stress_test/README.md b/tools/run_tests/stress_test/README.md deleted file mode 100644 index cc82b875cddd3aabf6ee458c190bf7ea9972815d..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/README.md +++ /dev/null @@ -1,76 +0,0 @@ -Running Stress tests on Google Container Engine -======================================= - -### **Glossary**: -* GCP: Google Cloud Platform -* GCE: Google Compute Engine -* GKE: Google Container Engine -* GCP console: https://console.cloud.google.com - -### **Setup Instructions** -#### *On GCP:* -1. Login to GCP with your Google account (for example, your @gmail account) at https://cloud.google.com. If do not have a Google account, you will have to create an account first. -2. Enable billing on Google cloud platform. Instructions [here](https://cloud.google.com/container-engine/docs/before-you-begin) (see the '*Enable billing*' section). -3. Create a Project from the [GCP console](https://console.cloud.google.com).i.e Click on the project dropdown box on the top right (to the right of the search box) and click '*Create a project*' option. -4. Enable the Container Engine API. Instructions [here](https://cloud.google.com/container-engine/docs/before-you-begin) (See the '*Enable the Container Engine API*’ section). Alternatively, you can do the following: - - Click on the '*Products & Services*' icon on the top left (i.e the icon with three small horizontal bars) and select '*API Manager*' - - Select the '*Container Engine API*' under '*Google Cloud APIs*' on the main page. Note that you might have to click on '*More*' under '*Google Cloud APIs*' to see the '*Container Engine API*' link - - Click on the '*Enable*' button. If the API is already enabled, the button's label would be '*Disable*' instead (do NOT click the button if its label is '*Disable*') -5. Create a Cluster from the GCP console. - - Go to the Container Engine section from GCP console i.e: Click on the '*Products & Services*' icon on the top left (i.e the icon with three small horizontal bars) and click on '*Container Engine*' - - Click '*Create Container Cluster*' and follow the instructions. - - The instructions for 'Name/Zone/MachineType' etc are [here](https://cloud.google.com/container-engine/docs/clusters/operations) (**NOTE**: The page also has instructions to setting up default clusters and configuring `kubectl`. We will be doing that later) - - For the cluster size, a smaller size of < 10 GCE instances is good enough for our use cases - assuming that we are planning to run a reasonably small number of stress client instances. For the machine type, something like '2 vCPUs 7.5 GB' (available in the drop down box) should be good enough. - - **IMPORTANT**: Before hitting the '*Create*' button, click on '*More*' link just above the '*Create*' button and Select '*Enabled*' for BigQuery , '*Enabled*' for Cloud Platform and '*Read/Write*' for Cloud User Accounts. - - Create the cluster by clicking '*Create*' button. - -#### *On your machine* (or the machine from which stress tests on GKE are launched): -1. You need a working gRPC repository on your machine. If you do not have it, clone the grpc repository from github (https://github.com/grpc/grpc) and follow the instructions [here](https://github.com/grpc/grpc/blob/master/INSTALL.md) -2. Install Docker. Instructions [here](https://docs.docker.com/engine/installation/) -3. Install Google Cloud SDK. Instructions [here](https://cloud.google.com/sdk/). This installs the `gcloud` tool -4. Install `kubectl`, Kubernetes command line tool using `gcloud`. i.e - - `$ gcloud components update kubectl` - - NOTE: If you are running this from a GCE instance, the command may fail with the following error: - ``` - You cannot perform this action because this Cloud SDK installation is - managed by an external package manager. If you would like to get the - latest version, please see our main download page at: - - https://developers.google.com/cloud/sdk/ - - ERROR: (gcloud.components.update) The component manager is disabled for this installation - ``` - -- If so, you will have to manually install Cloud SDK by doing the following - ```shell - $ # The following installs latest Cloud SDK and updates the PATH - $ # (Accept the default values when prompted) - $ curl https://sdk.cloud.google.com | bash - $ exec -l $SHELL - $ # Set the defaults. Pick the default GCE credentials when prompted (The service account - $ # name will have a name similar to: "xxx-compute@developer.gserviceaccount.com") - $ gcloud init - ``` - -5. Install Google python client apis: - - `‘$ sudo pip install --upgrade google-api-python-client’` - - **Note**: Do `$ sudo apt-get install python-pip` (or `$ easy_install -U pip`) if you do not have pip -6. Install the `requests` Python package if you don’t have it already by doing `sudo pip install requests`. More details regarding `requests` package are [here](http://docs.python-requests.org/en/master/user/install/) -7. Set the `gcloud` defaults: See the instructions [here](https://cloud.google.com/container-engine/docs/before-you-begin) under "*Set gcloud defaults*" section) - - Make sure you also fetch the cluster credentials for `kubectl` command to use. I.e `$ gcloud container clusters get-credentials CLUSTER_NAME` - -### **Launching Stress tests** - -The stress tests are launched by the following script (path is relative to GRPC root directory) : -`tools/run_tests/stress_test/run_stress_tests_on_gke.py` - -You can find out more details by using the `--help` flag. - - `<grpc_root_dir>$ tools/run_tests/stress_test/run_on_gke.py --help` - -> **Example** -> ```bash -> $ # Change to the grpc root directory -> $ cd $GRPC_ROOT -> $ tools/run_tests/stress_test/run_on_gke.py --project_id=sree-gce --config_file=tools/run_tests/stress_test/configs/opt.json -> ``` - -> The above runs the stress test on GKE under the project `sree-gce` in the default cluster (that you set by `gcloud` command earlier). The test settings (like number of client instances, servers, the parmeters to pass, test cases etc) are all loaded from the config file `$GRPC_ROOT/tools/run_tests/stress_test/opt.json` diff --git a/tools/run_tests/stress_test/STRESS_CLIENT_SPEC.md b/tools/run_tests/stress_test/STRESS_CLIENT_SPEC.md deleted file mode 100644 index 9f079beebc012d6a8f2e5a672d87cebbba49f0bb..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/STRESS_CLIENT_SPEC.md +++ /dev/null @@ -1,25 +0,0 @@ -Stress Test client Specification -========================= -This document specifies the features a stress test client should implement in order to work with the stress testing framework. The stress test clients are executed against the existing interop test servers. - -**Requirements** --------------- -**1.** A stress test client should be able to repeatedly execute one or more of the existing 'interop test cases'. It may just be a wrapper around the existing interop test client. The exact command line arguments the client should support are listed in _Table 1_ below. - -**2.** The stress test client must implement a metrics server defined by _[metrics.proto](https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/metrics.proto)_ and must expose _qps_ as a `Long`-valued Gauge. The client can track the overall _qps_ in one Gauge or in multiple Gauges (for example: One per Channel or Stub). - The framework periodically queries the _qps_ by calling the `GetAllGauges()` method (the framework assumes that all the returned Gauges are _qps_ Gauges and adds them up to determine the final qps) and uses this to determine if the stress test client is running or crashed or stalled. -> *Note:* In this context, the term _**qps**_ means _interop test cases per second_ (not _messages per second_ or _rpc calls per second_) - - -**Table 1:** Command line arguments that should be supported by the stress test client. - ->_**Note** The current C++ [stress client](https://github.com/grpc/grpc/blob/master/test/cpp/interop/stress_test.cc) supports more flags than those listed here but those flags will soon be deprecated._ - -Parameter | Description -----------------------|--------------------------------- -`--server_addresses` | The stress client should accept a list of server addresses in the following format:<br> ```<name_1>:<port_1>,<name_2>:<port_2>..<name_N>:<port_N>``` <br> _Note:_ `<name>` can be either server name or IP address.<br><br>_Type:_ string <br>_default:_ ```localhost:8080``` <br>_Example:_ ``foo.foobar.com:8080,bar.foobar.com:8080`` <br><br> Currently, the stress test framework only passes one server address to the client. -`--test_cases` | List of test cases along with the relative weights in the following format:<br> `<testcase_1:w_1>,<testcase_2:w_2>...<testcase_n:w_n>`. <br> The test cases names are the same as those currently used by the interop clients<br><br>_Type:_ string <br>_Example:_ `empty_unary:20,large_unary:10,empty_stream:70` <br>(The stress client would then make `empty_unary` calls 20% of the time, `large_unary` calls 10% of the time and `empty_stream` calls 70% of the time.) <br>_Note:_ The weights need not add up to 100. -`--test_duration_secs` | The test duration in seconds. A value of -1 means that the test should run forever until forcefully terminated. <br>_Type:_ int <br>_default:_ -1 -`--num_channels_per_server` | Number of channels (i.e connections) to each server. <br> _Type:_ int <br> _default:_ 1 <br><br> _Note:_ Unfortunately, the term `channel` is used differently in `grpc-java` and `C based grpc`. In this context, this really means "number of connections to the server" -`--num_stubs_per_channel ` | Number of client stubs per each connection to server.<br>_Type:_ int <br>_default:_ 1 -`--metrics_port` | The port at which the stress client exposes [QPS metrics](https://github.com/grpc/grpc/blob/master/src/proto/grpc/testing/metrics.proto). <br>_Type:_ int <br>_default:_ 8081 diff --git a/tools/run_tests/stress_test/configs/asan.json b/tools/run_tests/stress_test/configs/asan.json deleted file mode 100644 index 7ae11ccbf1e77a54d29823e74ad8451e454f5d18..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/asan.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_cxx_asan" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "asan" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 120, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "cxx_client_asan": { - "baseTemplate": "default", - "stressClientCmd": ["/var/local/git/grpc/bins/asan/stress_test"], - "metricsClientCmd": ["/var/local/git/grpc/bins/asan/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "cxx_server_asan": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/asan/interop_server"] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-asan": { - "serverTemplate": "cxx_server_asan", - "dockerImage": "grpc_stress_cxx_asan", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-asan": { - "clientTemplate": "cxx_client_asan", - "dockerImage": "grpc_stress_cxx_asan", - "numInstances": 5, - "serverPodSpec": "stress-server-asan" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8003, - "datasetIdNamePrefix": "stress_test_asan", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/csharp.json b/tools/run_tests/stress_test/configs/csharp.json deleted file mode 100644 index c438e08964cca385d05a2204d96e5fa40ee0cb02..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/csharp.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_csharp" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_csharp" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 100, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true", - "deadline_secs": 60 - } - } - }, - "templates": { - "csharp_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "mono", - "/var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.StressClient/bin/Debug/Grpc.IntegrationTesting.StressClient.exe" - ], - "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "csharp_server": { - "baseTemplate": "default", - "stressServerCmd": [ - "mono", - "/var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Server/bin/Debug/Grpc.IntegrationTesting.Server.exe" - ] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-csharp": { - "serverTemplate": "csharp_server", - "dockerImage": "grpc_stress_csharp", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-csharp": { - "clientTemplate": "csharp_client", - "dockerImage": "grpc_stress_csharp", - "numInstances": 10, - "serverPodSpec": "stress-server-csharp" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 100, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8009, - "datasetIdNamePrefix": "stress_test_csharp", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/go.json b/tools/run_tests/stress_test/configs/go.json deleted file mode 100644 index f1b2b523d3cb0cec2679f8df278f63f00ae9fb4b..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/go.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_go" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_go" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "go_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "go", - "run", - "/go/src/google.golang.org/grpc/stress/client/main.go" - ], - "metricsClientCmd": [ - "go", - "run", - "/go/src/google.golang.org/grpc/stress/metrics_client/main.go" - ] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "go_server": { - "baseTemplate": "default", - "stressServerCmd": [ - "go", - "run", - "/go/src/google.golang.org/grpc/interop/server/server.go" - ] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "go-stress-server": { - "serverTemplate": "go_server", - "dockerImage": "grpc_stress_go", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "go-stress-client": { - "clientTemplate": "go_client", - "dockerImage": "grpc_stress_go", - "numInstances": 15, - "serverPodSpec": "go-stress-server" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8007, - "datasetIdNamePrefix": "stress_test_go", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/java.json b/tools/run_tests/stress_test/configs/java.json deleted file mode 100644 index 92af63c6b55189b9779ef2636445a022095c00c6..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/java.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_java" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_java" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 100, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true", - "deadline_secs": 60 - }, - "env": { - "STRESSTEST_CLIENT_OPTS":"-Xmx3g -Xms3g -XX:NewSize=1500m -XX:MaxNewSize=1500m -XX:+UseConcMarkSweepGC" - } - } - }, - "templates": { - "java_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "/var/local/git/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/stresstest-client" - ], - "metricsClientCmd": [ - "/var/local/git/grpc/bins/opt/metrics_client" - ] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080, - "use_tls": "false" - }, - "env": { - "TEST_SERVER_OPTS":"-Xmx3g -Xms3g -XX:NewSize=1500m -XX:MaxNewSize=1500m -XX:+UseConcMarkSweepGC" - } - } - }, - "templates": { - "java_server": { - "baseTemplate": "default", - "stressServerCmd": [ - "/var/local/git/grpc-java/interop-testing/build/install/grpc-interop-testing/bin/test-server" - ] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "java-stress-server": { - "serverTemplate": "java_server", - "dockerImage": "grpc_stress_java", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "java-stress-client": { - "clientTemplate": "java_client", - "dockerImage": "grpc_stress_java", - "numInstances": 10, - "serverPodSpec": "java-stress-server" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 100, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8008, - "datasetIdNamePrefix": "stress_test_java", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/node-cxx.json b/tools/run_tests/stress_test/configs/node-cxx.json deleted file mode 100644 index 094c1236e71b43a8af96e9470cb3b2a6099088cf..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/node-cxx.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_cxx_opt" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "opt" - }, - "grpc_stress_node": { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_node" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "node_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh", - "node", - "/var/local/git/grpc/src/node/stress/stress_client.js" - ], - "metricsClientCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh", - "node", - "/var/local/git/grpc/src/node/stress/metrics_client.js" - ] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "cxx_server_opt": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-cxx-opt": { - "serverTemplate": "cxx_server_opt", - "dockerImage": "grpc_stress_cxx_opt", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-node": { - "clientTemplate": "node_client", - "dockerImage": "grpc_stress_node", - "numInstances": 20, - "serverPodSpec": "stress-server-cxx-opt" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8006, - "datasetIdNamePrefix": "stress_test_node_cxx_opt", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/node.json b/tools/run_tests/stress_test/configs/node.json deleted file mode 100644 index 85eb9e0003158e63ae696bbd1035c7240aa23395..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/node.json +++ /dev/null @@ -1,96 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_node" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_node" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "node_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh", - "node", - "/var/local/git/grpc/src/node/stress/stress_client.js" - ], - "metricsClientCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh", - "node", - "/var/local/git/grpc/src/node/stress/metrics_client.js" - ] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "node_server": { - "baseTemplate": "default", - "stressServerCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_node.sh", - "node", - "/var/local/git/grpc/src/node/interop/interop_server.js" - ] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "node-stress-server": { - "serverTemplate": "node_server", - "dockerImage": "grpc_stress_node", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "node-stress-client": { - "clientTemplate": "node_client", - "dockerImage": "grpc_stress_node", - "numInstances": 15, - "serverPodSpec": "node-stress-server" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8005, - "datasetIdNamePrefix": "stress_test_node", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/opt-tsan-asan.json b/tools/run_tests/stress_test/configs/opt-tsan-asan.json deleted file mode 100644 index fcb3678c02facb59442590ae8284ee3ca8c6e77b..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/opt-tsan-asan.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_cxx_opt" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "opt" - }, - "grpc_stress_cxx_tsan": { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "tsan" - }, - "grpc_stress_cxx_asan": { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "asan" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "cxx_client_opt": { - "baseTemplate": "default", - "stressClientCmd": ["/var/local/git/grpc/bins/opt/stress_test"], - "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"] - }, - "cxx_client_tsan": { - "baseTemplate": "default", - "stressClientCmd": ["/var/local/git/grpc/bins/tsan/stress_test"], - "metricsClientCmd": ["/var/local/git/grpc/bins/tsan/metrics_client"] - }, - "cxx_client_asan": { - "baseTemplate": "default", - "stressClientCmd": ["/var/local/git/grpc/bins/asan/stress_test"], - "metricsClientCmd": ["/var/local/git/grpc/bins/asan/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "cxx_server_opt": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"] - }, - "cxx_server_tsan": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/tsan/interop_server"] - }, - "cxx_server_asan": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/asan/interop_server"] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-opt": { - "serverTemplate": "cxx_server_opt", - "dockerImage": "grpc_stress_cxx_opt", - "numInstances": 1 - }, - "stress-server-tsan": { - "serverTemplate": "cxx_server_tsan", - "dockerImage": "grpc_stress_cxx_tsan", - "numInstances": 1 - }, - "stress-server-asan": { - "serverTemplate": "cxx_server_asan", - "dockerImage": "grpc_stress_cxx_asan", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-opt": { - "clientTemplate": "cxx_client_opt", - "dockerImage": "grpc_stress_cxx_opt", - "numInstances": 5, - "serverPodSpec": "stress-server-opt" - }, - "stress-client-tsan": { - "clientTemplate": "cxx_client_tsan", - "dockerImage": "grpc_stress_cxx_tsan", - "numInstances": 10, - "serverPodSpec": "stress-server-tsan" - }, - "stress-client-asan": { - "clientTemplate": "cxx_client_asan", - "dockerImage": "grpc_stress_cxx_asan", - "numInstances": 10, - "serverPodSpec": "stress-server-asan" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8004, - "datasetIdNamePrefix": "stress_test_opt_tsan", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} diff --git a/tools/run_tests/stress_test/configs/opt.json b/tools/run_tests/stress_test/configs/opt.json deleted file mode 100644 index 5e0e930d45307970b27adcdc3149dce03f311a79..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/opt.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_cxx_opt" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "opt" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "cxx_client_opt": { - "baseTemplate": "default", - "stressClientCmd": ["/var/local/git/grpc/bins/opt/stress_test"], - "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "cxx_server_opt": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-opt": { - "serverTemplate": "cxx_server_opt", - "dockerImage": "grpc_stress_cxx_opt", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-opt": { - "clientTemplate": "cxx_client_opt", - "dockerImage": "grpc_stress_cxx_opt", - "numInstances": 15, - "serverPodSpec": "stress-server-opt" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8001, - "datasetIdNamePrefix": "stress_test_opt", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/php-cxx.json b/tools/run_tests/stress_test/configs/php-cxx.json deleted file mode 100644 index 03254b368c86c1ca87850e9b0bb66260be40184d..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/php-cxx.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_cxx_opt" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "opt" - }, - "grpc_stress_php": { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_php" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081" - } - } - }, - "templates": { - "php_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "/var/local/git/grpc/src/php/bin/stress_client.sh" - ], - "metricsClientCmd": [ - "php", - "/var/local/git/grpc/src/php/tests/interop/metrics_client.php" - ] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "cxx_server_opt": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/opt/interop_server"] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-cxx-php": { - "serverTemplate": "cxx_server_opt", - "dockerImage": "grpc_stress_cxx_opt", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-php": { - "clientTemplate": "php_client", - "dockerImage": "grpc_stress_php", - "numInstances": 20, - "serverPodSpec": "stress-server-cxx-php" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8010, - "datasetIdNamePrefix": "stress_test_php_cxx_opt", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/python.json b/tools/run_tests/stress_test/configs/python.json deleted file mode 100644 index 4f85de1d5f6d40d493f98301dce2016d09e71010..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/python.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_python" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_python" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - }, - "env": { - "PYTHONPATH": "/var/local/git/grpc/src/python/gens:/var/local/git/grpc/src/python/grpcio", - "LD_LIBRARY_PATH":"/var/local/git/grpc/libs/opt" - } - } - }, - "templates": { - "python_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "python", - "/var/local/git/grpc/src/python/grpcio/tests/stress/client.py" - ], - "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - }, - "env": { - "PYTHONPATH": "/var/local/git/grpc/src/python/gens:/var/local/git/grpc/src/python/grpcio", - "LD_LIBRARY_PATH":"/var/local/git/grpc/libs/opt" - } - } - }, - "templates": { - "python_server": { - "baseTemplate": "default", - "stressServerCmd": [ - "python", - "/var/local/git/grpc/src/python/grpcio/tests/interop/server.py" - ] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "python-stress-server": { - "serverTemplate": "python_server", - "dockerImage": "grpc_stress_python", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "python-stress-client": { - "clientTemplate": "python_client", - "dockerImage": "grpc_stress_python", - "numInstances": 5, - "serverPodSpec": "python-stress-server" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8011, - "datasetIdNamePrefix": "stress_test_python", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/ruby.json b/tools/run_tests/stress_test/configs/ruby.json deleted file mode 100644 index 7e2afcbb69e5f2ef6a048bf04205d345860f5b98..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/ruby.json +++ /dev/null @@ -1,92 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_ruby" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_ruby" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 60, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "ruby_client": { - "baseTemplate": "default", - "stressClientCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_ruby.sh", - "ruby", - "/var/local/git/grpc/src/ruby/stress/stress_client.rb" - ], - "metricsClientCmd": ["/var/local/git/grpc/bins/opt/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "ruby_server": { - "baseTemplate": "default", - "stressServerCmd": [ - "/var/local/git/grpc/tools/gcp/stress_test/run_ruby.sh", - "ruby", - "/var/local/git/grpc/src/ruby/pb/test/server.rb" - ] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-ruby": { - "serverTemplate": "ruby_server", - "dockerImage": "grpc_stress_ruby", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-ruby": { - "clientTemplate": "ruby_client", - "dockerImage": "grpc_stress_ruby", - "numInstances": 10, - "serverPodSpec": "stress-server-ruby" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8001, - "datasetIdNamePrefix": "stress_test_ruby", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/configs/tsan.json b/tools/run_tests/stress_test/configs/tsan.json deleted file mode 100644 index abc759c79daef226d0894a2c1271b9c3347f4aa1..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/configs/tsan.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "dockerImages": { - "grpc_stress_cxx_tsan" : { - "buildScript": "tools/run_tests/dockerize/build_interop_stress_image.sh", - "dockerFileDir": "grpc_interop_stress_cxx", - "buildType": "tsan" - } - }, - - "clientTemplates": { - "baseTemplates": { - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_client.py", - "pollIntervalSecs": 120, - "clientArgs": { - "num_channels_per_server":5, - "num_stubs_per_channel":10, - "test_cases": "empty_unary:1,large_unary:1,client_streaming:1,server_streaming:1,empty_stream:1", - "metrics_port": 8081 - }, - "metricsPort": 8081, - "metricsArgs": { - "metrics_server_address": "localhost:8081", - "total_only": "true" - } - } - }, - "templates": { - "cxx_client_tsan": { - "baseTemplate": "default", - "stressClientCmd": ["/var/local/git/grpc/bins/tsan/stress_test"], - "metricsClientCmd": ["/var/local/git/grpc/bins/tsan/metrics_client"] - } - } - }, - - "serverTemplates": { - "baseTemplates":{ - "default": { - "wrapperScriptPath": "/var/local/git/grpc/tools/gcp/stress_test/run_server.py", - "serverPort": 8080, - "serverArgs": { - "port": 8080 - } - } - }, - "templates": { - "cxx_server_tsan": { - "baseTemplate": "default", - "stressServerCmd": ["/var/local/git/grpc/bins/tsan/interop_server"] - } - } - }, - - "testMatrix": { - "serverPodSpecs": { - "stress-server-tsan": { - "serverTemplate": "cxx_server_tsan", - "dockerImage": "grpc_stress_cxx_tsan", - "numInstances": 1 - } - }, - - "clientPodSpecs": { - "stress-client-tsan": { - "clientTemplate": "cxx_client_tsan", - "dockerImage": "grpc_stress_cxx_tsan", - "numInstances": 5, - "serverPodSpec": "stress-server-tsan" - } - } - }, - - "globalSettings": { - "buildDockerImages": true, - "pollIntervalSecs": 60, - "testDurationSecs": 7200, - "kubernetesProxyPort": 8002, - "datasetIdNamePrefix": "stress_test_tsan", - "summaryTableId": "summary", - "qpsTableId": "qps", - "podWarmupSecs": 60 - } -} - diff --git a/tools/run_tests/stress_test/print_summary.py b/tools/run_tests/stress_test/print_summary.py deleted file mode 100755 index 6f4ada2f4fd23a6e341323f25f2f2b198ae71dee..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/print_summary.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# Copyright 2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import argparse -import os -import sys - -stress_test_utils_dir = os.path.abspath(os.path.join( - os.path.dirname(__file__), '../../gcp/stress_test')) -sys.path.append(stress_test_utils_dir) -from stress_test_utils import BigQueryHelper - -argp = argparse.ArgumentParser( - description='Print summary tables', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -argp.add_argument('--gcp_project_id', - required=True, - help='The Google Cloud Platform Project Id') -argp.add_argument('--dataset_id', type=str, required=True) -argp.add_argument('--run_id', type=str, required=True) -argp.add_argument('--summary_table_id', type=str, default='summary') -argp.add_argument('--qps_table_id', type=str, default='qps') -argp.add_argument('--summary_only', action='store_true', default=True) - -if __name__ == '__main__': - args = argp.parse_args() - bq_helper = BigQueryHelper(args.run_id, '', '', args.gcp_project_id, - args.dataset_id, args.summary_table_id, - args.qps_table_id) - bq_helper.initialize() - if not args.summary_only: - bq_helper.print_qps_records() - bq_helper.print_summary_records() diff --git a/tools/run_tests/stress_test/run_on_gke.py b/tools/run_tests/stress_test/run_on_gke.py deleted file mode 100755 index b190ebde7a4f44d697b7eab4b23515755a6553d6..0000000000000000000000000000000000000000 --- a/tools/run_tests/stress_test/run_on_gke.py +++ /dev/null @@ -1,674 +0,0 @@ -#!/usr/bin/env python -# Copyright 2015-2016, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -from __future__ import print_function - -import argparse -import datetime -import json -import os -import subprocess -import sys -import time - -stress_test_utils_dir = os.path.abspath(os.path.join( - os.path.dirname(__file__), '../../gcp/stress_test')) -sys.path.append(stress_test_utils_dir) -from stress_test_utils import BigQueryHelper - -kubernetes_api_dir = os.path.abspath(os.path.join( - os.path.dirname(__file__), '../../gcp/utils')) -sys.path.append(kubernetes_api_dir) - -import kubernetes_api - - -class GlobalSettings: - - def __init__(self, gcp_project_id, build_docker_images, - test_poll_interval_secs, test_duration_secs, - kubernetes_proxy_port, dataset_id_prefix, summary_table_id, - qps_table_id, pod_warmup_secs): - self.gcp_project_id = gcp_project_id - self.build_docker_images = build_docker_images - self.test_poll_interval_secs = test_poll_interval_secs - self.test_duration_secs = test_duration_secs - self.kubernetes_proxy_port = kubernetes_proxy_port - self.dataset_id_prefix = dataset_id_prefix - self.summary_table_id = summary_table_id - self.qps_table_id = qps_table_id - self.pod_warmup_secs = pod_warmup_secs - - -class ClientTemplate: - """ Contains all the common settings that are used by a stress client """ - - def __init__(self, name, stress_client_cmd, metrics_client_cmd, metrics_port, - wrapper_script_path, poll_interval_secs, client_args_dict, - metrics_args_dict, will_run_forever, env_dict): - self.name = name - self.stress_client_cmd = stress_client_cmd - self.metrics_client_cmd = metrics_client_cmd - self.metrics_port = metrics_port - self.wrapper_script_path = wrapper_script_path - self.poll_interval_secs = poll_interval_secs - self.client_args_dict = client_args_dict - self.metrics_args_dict = metrics_args_dict - self.will_run_forever = will_run_forever - self.env_dict = env_dict - - -class ServerTemplate: - """ Contains all the common settings used by a stress server """ - - def __init__(self, name, server_cmd, wrapper_script_path, server_port, - server_args_dict, will_run_forever, env_dict): - self.name = name - self.server_cmd = server_cmd - self.wrapper_script_path = wrapper_script_path - self.server_port = server_port - self.server_args_dict = server_args_dict - self.will_run_forever = will_run_forever - self.env_dict = env_dict - - -class DockerImage: - """ Represents properties of a Docker image. Provides methods to build the - image and push it to GKE registry - """ - - def __init__(self, gcp_project_id, image_name, build_script_path, - dockerfile_dir, build_type): - """Args: - - image_name: The docker image name - tag_name: The additional tag name. This is the name used when pushing the - docker image to GKE registry - build_script_path: The path to the build script that builds this docker - image - dockerfile_dir: The name of the directory under - '<grpc_root>/tools/dockerfile' that contains the dockerfile - """ - self.image_name = image_name - self.gcp_project_id = gcp_project_id - self.build_script_path = build_script_path - self.dockerfile_dir = dockerfile_dir - self.build_type = build_type - self.tag_name = self._make_tag_name(gcp_project_id, image_name) - - def _make_tag_name(self, project_id, image_name): - return 'gcr.io/%s/%s' % (project_id, image_name) - - def build_image(self): - print('Building docker image: %s (tag: %s)' % (self.image_name, - self.tag_name)) - os.environ['INTEROP_IMAGE'] = self.image_name - os.environ['INTEROP_IMAGE_REPOSITORY_TAG'] = self.tag_name - os.environ['BASE_NAME'] = self.dockerfile_dir - os.environ['BUILD_TYPE'] = self.build_type - print('DEBUG: path: ', self.build_script_path) - if subprocess.call(args=[self.build_script_path]) != 0: - print('Error in building the Docker image') - return False - return True - - def push_to_gke_registry(self): - cmd = ['gcloud', 'docker', 'push', self.tag_name] - print('Pushing %s to the GKE registry..' % self.tag_name) - if subprocess.call(args=cmd) != 0: - print('Error in pushing the image %s to the GKE registry' % - self.tag_name) - return False - return True - - -class ServerPodSpec: - """ Contains the information required to launch server pods. """ - - def __init__(self, name, server_template, docker_image, num_instances): - self.name = name - self.template = server_template - self.docker_image = docker_image - self.num_instances = num_instances - - def pod_names(self): - """ Return a list of names of server pods to create. """ - return ['%s-%d' % (self.name, i) for i in range(1, self.num_instances + 1)] - - def server_addresses(self): - """ Return string of server addresses in the following format: - '<server_pod_name_1>:<server_port>,<server_pod_name_2>:<server_port>...' - """ - return ','.join(['%s:%d' % (pod_name, self.template.server_port) - for pod_name in self.pod_names()]) - - -class ClientPodSpec: - """ Contains the information required to launch client pods """ - - def __init__(self, name, client_template, docker_image, num_instances, - server_addresses): - self.name = name - self.template = client_template - self.docker_image = docker_image - self.num_instances = num_instances - self.server_addresses = server_addresses - - def pod_names(self): - """ Return a list of names of client pods to create """ - return ['%s-%d' % (self.name, i) for i in range(1, self.num_instances + 1)] - - # The client args in the template do not have server addresses. This function - # adds the server addresses and returns the updated client args - def get_client_args_dict(self): - args_dict = self.template.client_args_dict.copy() - args_dict['server_addresses'] = self.server_addresses - return args_dict - - -class Gke: - """ Class that has helper methods to interact with GKE """ - - class KubernetesProxy: - """Class to start a proxy on localhost to talk to the Kubernetes API server""" - - def __init__(self, port): - cmd = ['kubectl', 'proxy', '--port=%d' % port] - self.p = subprocess.Popen(args=cmd) - time.sleep(2) - print('\nStarted kubernetes proxy on port: %d' % port) - - def __del__(self): - if self.p is not None: - print('Shutting down Kubernetes proxy..') - self.p.kill() - - def __init__(self, project_id, run_id, dataset_id, summary_table_id, - qps_table_id, kubernetes_port): - self.project_id = project_id - self.run_id = run_id - self.dataset_id = dataset_id - self.summary_table_id = summary_table_id - self.qps_table_id = qps_table_id - - # The environment variables we would like to pass to every pod (both client - # and server) launched in GKE - self.gke_env = { - 'RUN_ID': self.run_id, - 'GCP_PROJECT_ID': self.project_id, - 'DATASET_ID': self.dataset_id, - 'SUMMARY_TABLE_ID': self.summary_table_id, - 'QPS_TABLE_ID': self.qps_table_id - } - - self.kubernetes_port = kubernetes_port - # Start kubernetes proxy - self.kubernetes_proxy = Gke.KubernetesProxy(kubernetes_port) - - def _args_dict_to_str(self, args_dict): - return ' '.join('--%s=%s' % (k, args_dict[k]) for k in args_dict.keys()) - - def launch_servers(self, server_pod_spec): - is_success = True - - # The command to run inside the container is the wrapper script (which then - # launches the actual server) - container_cmd = server_pod_spec.template.wrapper_script_path - - # The parameters to the wrapper script (defined in - # server_pod_spec.template.wrapper_script_path) are are injected into the - # container via environment variables - server_env = self.gke_env.copy() - server_env.update(server_pod_spec.template.env_dict) - server_env.update({ - 'STRESS_TEST_IMAGE_TYPE': 'SERVER', - 'STRESS_TEST_CMD': server_pod_spec.template.server_cmd, - 'STRESS_TEST_ARGS_STR': self._args_dict_to_str( - server_pod_spec.template.server_args_dict), - 'WILL_RUN_FOREVER': str(server_pod_spec.template.will_run_forever) - }) - - for pod_name in server_pod_spec.pod_names(): - server_env['POD_NAME'] = pod_name - print('Creating server: %s' % pod_name) - is_success = kubernetes_api.create_pod_and_service( - 'localhost', - self.kubernetes_port, - 'default', # Use 'default' namespace - pod_name, - server_pod_spec.docker_image.tag_name, - [server_pod_spec.template.server_port], # Ports to expose on the pod - [container_cmd], - [], # Args list is empty since we are passing all args via env variables - server_env, - True # Headless = True for server to that GKE creates a DNS record for pod_name - ) - if not is_success: - print('Error in launching server: %s' % pod_name) - break - - if is_success: - print('Successfully created server(s)') - - return is_success - - def launch_clients(self, client_pod_spec): - is_success = True - - # The command to run inside the container is the wrapper script (which then - # launches the actual stress client) - container_cmd = client_pod_spec.template.wrapper_script_path - - # The parameters to the wrapper script (defined in - # client_pod_spec.template.wrapper_script_path) are are injected into the - # container via environment variables - client_env = self.gke_env.copy() - client_env.update(client_pod_spec.template.env_dict) - client_env.update({ - 'STRESS_TEST_IMAGE_TYPE': 'CLIENT', - 'STRESS_TEST_CMD': client_pod_spec.template.stress_client_cmd, - 'STRESS_TEST_ARGS_STR': self._args_dict_to_str( - client_pod_spec.get_client_args_dict()), - 'METRICS_CLIENT_CMD': client_pod_spec.template.metrics_client_cmd, - 'METRICS_CLIENT_ARGS_STR': self._args_dict_to_str( - client_pod_spec.template.metrics_args_dict), - 'POLL_INTERVAL_SECS': str(client_pod_spec.template.poll_interval_secs), - 'WILL_RUN_FOREVER': str(client_pod_spec.template.will_run_forever) - }) - - for pod_name in client_pod_spec.pod_names(): - client_env['POD_NAME'] = pod_name - print('Creating client: %s' % pod_name) - is_success = kubernetes_api.create_pod_and_service( - 'localhost', - self.kubernetes_port, - 'default', # default namespace, - pod_name, - client_pod_spec.docker_image.tag_name, - [client_pod_spec.template.metrics_port], # Ports to expose on the pod - [container_cmd], - [], # Empty args list since all args are passed via env variables - client_env, - True # Client is a headless service (no need for an external ip) - ) - - if not is_success: - print('Error in launching client %s' % pod_name) - break - - if is_success: - print('Successfully created all client(s)') - - return is_success - - def _delete_pods(self, pod_name_list): - is_success = True - for pod_name in pod_name_list: - print('Deleting %s' % pod_name) - is_success = kubernetes_api.delete_pod_and_service( - 'localhost', - self.kubernetes_port, - 'default', # default namespace - pod_name) - - if not is_success: - print('Error in deleting pod %s' % pod_name) - break - - if is_success: - print('Successfully deleted all pods') - - return is_success - - def delete_servers(self, server_pod_spec): - return self._delete_pods(server_pod_spec.pod_names()) - - def delete_clients(self, client_pod_spec): - return self._delete_pods(client_pod_spec.pod_names()) - - -class Config: - - def __init__(self, config_filename, gcp_project_id): - print('Loading configuration...') - config_dict = self._load_config(config_filename) - - self.global_settings = self._parse_global_settings(config_dict, - gcp_project_id) - self.docker_images_dict = self._parse_docker_images( - config_dict, self.global_settings.gcp_project_id) - self.client_templates_dict = self._parse_client_templates(config_dict) - self.server_templates_dict = self._parse_server_templates(config_dict) - self.server_pod_specs_dict = self._parse_server_pod_specs( - config_dict, self.docker_images_dict, self.server_templates_dict) - self.client_pod_specs_dict = self._parse_client_pod_specs( - config_dict, self.docker_images_dict, self.client_templates_dict, - self.server_pod_specs_dict) - print('Loaded Configuaration.') - - def _parse_global_settings(self, config_dict, gcp_project_id): - global_settings_dict = config_dict['globalSettings'] - return GlobalSettings(gcp_project_id, - global_settings_dict['buildDockerImages'], - global_settings_dict['pollIntervalSecs'], - global_settings_dict['testDurationSecs'], - global_settings_dict['kubernetesProxyPort'], - global_settings_dict['datasetIdNamePrefix'], - global_settings_dict['summaryTableId'], - global_settings_dict['qpsTableId'], - global_settings_dict['podWarmupSecs']) - - def _parse_docker_images(self, config_dict, gcp_project_id): - """Parses the 'dockerImages' section of the config file and returns a - Dictionary of 'DockerImage' objects keyed by docker image names""" - docker_images_dict = {} - - docker_config_dict = config_dict['dockerImages'] - for image_name in docker_config_dict.keys(): - build_script_path = docker_config_dict[image_name]['buildScript'] - dockerfile_dir = docker_config_dict[image_name]['dockerFileDir'] - build_type = docker_config_dict[image_name].get('buildType', 'opt') - docker_images_dict[image_name] = DockerImage(gcp_project_id, image_name, - build_script_path, - dockerfile_dir, build_type) - return docker_images_dict - - def _parse_client_templates(self, config_dict): - """Parses the 'clientTemplates' section of the config file and returns a - Dictionary of 'ClientTemplate' objects keyed by client template names. - - Note: The 'baseTemplates' sub section of the config file contains templates - with default values and the 'templates' sub section contains the actual - client templates (which refer to the base template name to use for default - values). - """ - client_templates_dict = {} - - templates_dict = config_dict['clientTemplates']['templates'] - base_templates_dict = config_dict['clientTemplates'].get('baseTemplates', - {}) - for template_name in templates_dict.keys(): - # temp_dict is a temporary dictionary that merges base template dictionary - # and client template dictionary (with client template dictionary values - # overriding base template values) - temp_dict = {} - - base_template_name = templates_dict[template_name].get('baseTemplate') - if not base_template_name is None: - temp_dict = base_templates_dict[base_template_name].copy() - - temp_dict.update(templates_dict[template_name]) - - # Create and add ClientTemplate object to the final client_templates_dict - stress_client_cmd = ' '.join(temp_dict['stressClientCmd']) - metrics_client_cmd = ' '.join(temp_dict['metricsClientCmd']) - client_templates_dict[template_name] = ClientTemplate( - template_name, stress_client_cmd, metrics_client_cmd, - temp_dict['metricsPort'], temp_dict['wrapperScriptPath'], - temp_dict['pollIntervalSecs'], temp_dict['clientArgs'].copy(), - temp_dict['metricsArgs'].copy(), temp_dict.get('willRunForever', 1), - temp_dict.get('env', {}).copy()) - - return client_templates_dict - - def _parse_server_templates(self, config_dict): - """Parses the 'serverTemplates' section of the config file and returns a - Dictionary of 'serverTemplate' objects keyed by server template names. - - Note: The 'baseTemplates' sub section of the config file contains templates - with default values and the 'templates' sub section contains the actual - server templates (which refer to the base template name to use for default - values). - """ - server_templates_dict = {} - - templates_dict = config_dict['serverTemplates']['templates'] - base_templates_dict = config_dict['serverTemplates'].get('baseTemplates', - {}) - - for template_name in templates_dict.keys(): - # temp_dict is a temporary dictionary that merges base template dictionary - # and server template dictionary (with server template dictionary values - # overriding base template values) - temp_dict = {} - - base_template_name = templates_dict[template_name].get('baseTemplate') - if not base_template_name is None: - temp_dict = base_templates_dict[base_template_name].copy() - - temp_dict.update(templates_dict[template_name]) - - # Create and add ServerTemplate object to the final server_templates_dict - stress_server_cmd = ' '.join(temp_dict['stressServerCmd']) - server_templates_dict[template_name] = ServerTemplate( - template_name, stress_server_cmd, temp_dict['wrapperScriptPath'], - temp_dict['serverPort'], temp_dict['serverArgs'].copy(), - temp_dict.get('willRunForever', 1), temp_dict.get('env', {}).copy()) - - return server_templates_dict - - def _parse_server_pod_specs(self, config_dict, docker_images_dict, - server_templates_dict): - """Parses the 'serverPodSpecs' sub-section (under 'testMatrix' section) of - the config file and returns a Dictionary of 'ServerPodSpec' objects keyed - by server pod spec names""" - server_pod_specs_dict = {} - - pod_specs_dict = config_dict['testMatrix'].get('serverPodSpecs', {}) - - for pod_name in pod_specs_dict.keys(): - server_template_name = pod_specs_dict[pod_name]['serverTemplate'] - docker_image_name = pod_specs_dict[pod_name]['dockerImage'] - num_instances = pod_specs_dict[pod_name].get('numInstances', 1) - - # Create and add the ServerPodSpec object to the final - # server_pod_specs_dict - server_pod_specs_dict[pod_name] = ServerPodSpec( - pod_name, server_templates_dict[server_template_name], - docker_images_dict[docker_image_name], num_instances) - - return server_pod_specs_dict - - def _parse_client_pod_specs(self, config_dict, docker_images_dict, - client_templates_dict, server_pod_specs_dict): - """Parses the 'clientPodSpecs' sub-section (under 'testMatrix' section) of - the config file and returns a Dictionary of 'ClientPodSpec' objects keyed - by client pod spec names""" - client_pod_specs_dict = {} - - pod_specs_dict = config_dict['testMatrix'].get('clientPodSpecs', {}) - for pod_name in pod_specs_dict.keys(): - client_template_name = pod_specs_dict[pod_name]['clientTemplate'] - docker_image_name = pod_specs_dict[pod_name]['dockerImage'] - num_instances = pod_specs_dict[pod_name]['numInstances'] - - # Get the server addresses from the server pod spec object - server_pod_spec_name = pod_specs_dict[pod_name]['serverPodSpec'] - server_addresses = server_pod_specs_dict[ - server_pod_spec_name].server_addresses() - - client_pod_specs_dict[pod_name] = ClientPodSpec( - pod_name, client_templates_dict[client_template_name], - docker_images_dict[docker_image_name], num_instances, - server_addresses) - - return client_pod_specs_dict - - def _load_config(self, config_filename): - """Opens the config file and converts the Json text to Dictionary""" - if not os.path.isabs(config_filename): - raise Exception('Config objects expects an absolute file path. ' - 'config file name passed: %s' % config_filename) - with open(config_filename) as config_file: - return json.load(config_file) - - -def run_tests(config): - """ The main function that launches the stress tests """ - # Build docker images and push to GKE registry - if config.global_settings.build_docker_images: - for name, docker_image in config.docker_images_dict.iteritems(): - if not (docker_image.build_image() and - docker_image.push_to_gke_registry()): - return False - - # Create a unique id for this run (Note: Using timestamp instead of UUID to - # make it easier to deduce the date/time of the run just by looking at the run - # run id. This is useful in debugging when looking at records in Biq query) - run_id = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S') - dataset_id = '%s_%s' % (config.global_settings.dataset_id_prefix, run_id) - print('Run id:', run_id) - print('Dataset id:', dataset_id) - - bq_helper = BigQueryHelper(run_id, '', '', - config.global_settings.gcp_project_id, dataset_id, - config.global_settings.summary_table_id, - config.global_settings.qps_table_id) - bq_helper.initialize() - - gke = Gke(config.global_settings.gcp_project_id, run_id, dataset_id, - config.global_settings.summary_table_id, - config.global_settings.qps_table_id, - config.global_settings.kubernetes_proxy_port) - - is_success = True - - try: - print('Launching servers..') - for name, server_pod_spec in config.server_pod_specs_dict.iteritems(): - if not gke.launch_servers(server_pod_spec): - is_success = False # is_success is checked in the 'finally' block - return False - - print('Launched servers. Waiting for %d seconds for the server pods to be ' - 'fully online') % config.global_settings.pod_warmup_secs - time.sleep(config.global_settings.pod_warmup_secs) - - for name, client_pod_spec in config.client_pod_specs_dict.iteritems(): - if not gke.launch_clients(client_pod_spec): - is_success = False # is_success is checked in the 'finally' block - return False - - print('Launched all clients. Waiting for %d seconds for the client pods to ' - 'be fully online') % config.global_settings.pod_warmup_secs - time.sleep(config.global_settings.pod_warmup_secs) - - start_time = datetime.datetime.now() - end_time = start_time + datetime.timedelta( - seconds=config.global_settings.test_duration_secs) - print('Running the test until %s' % end_time.isoformat()) - - while True: - if datetime.datetime.now() > end_time: - print('Test was run for %d seconds' % - config.global_settings.test_duration_secs) - break - - # Check if either stress server or clients have failed (btw, the bq_helper - # monitors all the rows in the summary table and checks if any of them - # have a failure status) - if bq_helper.check_if_any_tests_failed(): - is_success = False - print('Some tests failed.') - break # Don't 'return' here. We still want to call bq_helper to print qps/summary tables - - # Tests running fine. Wait until next poll time to check the status - print('Sleeping for %d seconds..' % - config.global_settings.test_poll_interval_secs) - time.sleep(config.global_settings.test_poll_interval_secs) - - # Print BiqQuery tables - bq_helper.print_qps_records() - bq_helper.print_summary_records() - - finally: - # If there was a test failure, we should not delete the pods since they - # would contain useful debug information (logs, core dumps etc) - if is_success: - for name, server_pod_spec in config.server_pod_specs_dict.iteritems(): - gke.delete_servers(server_pod_spec) - for name, client_pod_spec in config.client_pod_specs_dict.iteritems(): - gke.delete_clients(client_pod_spec) - - return is_success - - -def tear_down(config): - gke = Gke(config.global_settings.gcp_project_id, '', '', - config.global_settings.summary_table_id, - config.global_settings.qps_table_id, - config.global_settings.kubernetes_proxy_port) - for name, server_pod_spec in config.server_pod_specs_dict.iteritems(): - gke.delete_servers(server_pod_spec) - for name, client_pod_spec in config.client_pod_specs_dict.iteritems(): - gke.delete_clients(client_pod_spec) - - -argp = argparse.ArgumentParser( - description='Launch stress tests in GKE', - formatter_class=argparse.ArgumentDefaultsHelpFormatter) -argp.add_argument('--gcp_project_id', - required=True, - help='The Google Cloud Platform Project Id') -argp.add_argument('--config_file', - required=True, - type=str, - help='The test config file') -argp.add_argument('--tear_down', action='store_true', default=False) - -if __name__ == '__main__': - args = argp.parse_args() - - config_filename = args.config_file - - # Since we will be changing the current working directory to grpc root in the - # next step, we should check if the config filename path is a relative path - # (i.e a path relative to the current working directory) and if so, convert it - # to abosulte path - if not os.path.isabs(config_filename): - config_filename = os.path.abspath(config_filename) - - config = Config(config_filename, args.gcp_project_id) - - # Change current working directory to grpc root - # (This is important because all relative file paths in the config file are - # supposed to interpreted as relative to the GRPC root) - grpc_root = os.path.abspath(os.path.join( - os.path.dirname(sys.argv[0]), '../../..')) - os.chdir(grpc_root) - - # Note that tear_down is only in cases where we want to manually tear down a - # test that for some reason run_tests() could not cleanup - if args.tear_down: - tear_down(config) - sys.exit(1) - - if not run_tests(config): - sys.exit(1) diff --git a/tools/ubsan_suppressions.txt b/tools/ubsan_suppressions.txt index 9869f98a22e6507e64bc0bd927f782290d064edb..f87ed1856543561e5654fec9e718a57fbd4648f0 100644 --- a/tools/ubsan_suppressions.txt +++ b/tools/ubsan_suppressions.txt @@ -4,4 +4,6 @@ nonnull-attribute:CBB_add_bytes nonnull-attribute:rsa_blinding_get nonnull-attribute:ssl_copy_key_material alignment:CRYPTO_cbc128_encrypt +nonnull-attribute:google::protobuf::DescriptorBuilder::BuildFileImpl +nonnull-attribute:google::protobuf::TextFormat::Printer::TextGenerator::Write diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln index 296a976731c22cef1bbcdbc4fbf8f3059fcd5ff8..97a75e776234371b85fbbe0cdc08514d2b793a25 100644 --- a/vsprojects/buildtests_c.sln +++ b/vsprojects/buildtests_c.sln @@ -162,6 +162,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "channel_create_test", "vcxp {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "check_epollexclusive", "vcxproj\.\check_epollexclusive\check_epollexclusive.vcxproj", "{03306445-5BA0-289C-02AB-513DE6C52124}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chttp2_hpack_encoder_test", "vcxproj\test\chttp2_hpack_encoder_test\chttp2_hpack_encoder_test.vcxproj", "{19F92966-3B0E-4FF8-CD7C-435D353E079E}" ProjectSection(myProperties) = preProject lib = "False" @@ -1938,6 +1947,22 @@ Global {AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release-DLL|Win32.Build.0 = Release|Win32 {AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release-DLL|x64.ActiveCfg = Release|x64 {AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release-DLL|x64.Build.0 = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|Win32.ActiveCfg = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|x64.ActiveCfg = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|Win32.ActiveCfg = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|x64.ActiveCfg = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|Win32.Build.0 = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|x64.Build.0 = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|Win32.Build.0 = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|x64.Build.0 = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|x64.Build.0 = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|Win32.Build.0 = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|x64.ActiveCfg = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|x64.Build.0 = Release|x64 {19F92966-3B0E-4FF8-CD7C-435D353E079E}.Debug|Win32.ActiveCfg = Debug|Win32 {19F92966-3B0E-4FF8-CD7C-435D353E079E}.Debug|x64.ActiveCfg = Debug|x64 {19F92966-3B0E-4FF8-CD7C-435D353E079E}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/grpc.sln b/vsprojects/grpc.sln index 97378e0a0f85984fc6f4a02fd91f4cbac3e5bc86..307ae4b59908e354d29491e08db34aafcb033f30 100644 --- a/vsprojects/grpc.sln +++ b/vsprojects/grpc.sln @@ -8,6 +8,15 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ares", "vcxproj\.\ares\ares lib = "True" EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "check_epollexclusive", "vcxproj\.\check_epollexclusive\check_epollexclusive.vcxproj", "{03306445-5BA0-289C-02AB-513DE6C52124}" + ProjectSection(myProperties) = preProject + lib = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9} + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_hpack_tables", "vcxproj\.\gen_hpack_tables\gen_hpack_tables.vcxproj", "{FCDEA4C7-7F26-05DB-D08F-A08F499026E6}" ProjectSection(myProperties) = preProject lib = "False" @@ -190,6 +199,22 @@ Global {1769D06D-F18C-B4C2-B019-31D7F83F3C9A}.Release-DLL|Win32.Build.0 = Release|Win32 {1769D06D-F18C-B4C2-B019-31D7F83F3C9A}.Release-DLL|x64.ActiveCfg = Release|x64 {1769D06D-F18C-B4C2-B019-31D7F83F3C9A}.Release-DLL|x64.Build.0 = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|Win32.ActiveCfg = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|x64.ActiveCfg = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|Win32.ActiveCfg = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|x64.ActiveCfg = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|Win32.Build.0 = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug|x64.Build.0 = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|Win32.Build.0 = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release|x64.Build.0 = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|Win32.ActiveCfg = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|Win32.Build.0 = Debug|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|x64.ActiveCfg = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Debug-DLL|x64.Build.0 = Debug|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|Win32.ActiveCfg = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|Win32.Build.0 = Release|Win32 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|x64.ActiveCfg = Release|x64 + {03306445-5BA0-289C-02AB-513DE6C52124}.Release-DLL|x64.Build.0 = Release|x64 {FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Debug|Win32.ActiveCfg = Debug|Win32 {FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Debug|x64.ActiveCfg = Debug|x64 {FCDEA4C7-7F26-05DB-D08F-A08F499026E6}.Release|Win32.ActiveCfg = Release|Win32 diff --git a/vsprojects/protoc.props b/vsprojects/protoc.props index 87fff8f12884fb6e0461e7947fe00a271f4e52cf..6c842c282ee13ea638354fb7221185c7073d809b 100644 --- a/vsprojects/protoc.props +++ b/vsprojects/protoc.props @@ -1 +1 @@ -<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <ClCompile> <DisableSpecificWarnings>4244;4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\build\solution\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemGroup /> </Project> \ No newline at end of file +<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ImportGroup Label="PropertySheets" /> <PropertyGroup Label="UserMacros" /> <PropertyGroup /> <ItemDefinitionGroup> <ClCompile> <DisableSpecificWarnings>4244;4267;4800;%(DisableSpecificWarnings)</DisableSpecificWarnings> </ClCompile> <Link> <AdditionalDependencies>libprotoc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(SolutionDir)\..\third_party\protobuf\cmake\build\solution\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> </Link> </ItemDefinitionGroup> <ItemGroup /> </Project> \ No newline at end of file diff --git a/vsprojects/vcxproj/check_epollexclusive/check_epollexclusive.vcxproj b/vsprojects/vcxproj/check_epollexclusive/check_epollexclusive.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..36e6fee0db84f2ef59a000a8d6dc1ae94ed8bfbd --- /dev/null +++ b/vsprojects/vcxproj/check_epollexclusive/check_epollexclusive.vcxproj @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{03306445-5BA0-289C-02AB-513DE6C52124}</ProjectGuid> + <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected> + <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration"> + <PlatformToolset>v100</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration"> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration"> + <PlatformToolset>v120</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration"> + <PlatformToolset>v140</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + <Import Project="$(SolutionDir)\..\vsprojects\global.props" /> + <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)'=='Debug'"> + <TargetName>check_epollexclusive</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'"> + <TargetName>check_epollexclusive</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PrecompiledHeader>NotUsing</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>MaxSpeed</Optimization> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <SDLCheck>true</SDLCheck> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <TreatWarningAsError>true</TreatWarningAsError> + <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat> + <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation> + <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + + <ItemGroup> + <ClCompile Include="$(SolutionDir)\..\test\build\check_epollexclusive.c"> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj"> + <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project> + </ProjectReference> + <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj"> + <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + </Target> +</Project> + diff --git a/vsprojects/vcxproj/check_epollexclusive/check_epollexclusive.vcxproj.filters b/vsprojects/vcxproj/check_epollexclusive/check_epollexclusive.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..5572541d1da5501ae1ff4a0f2a3965b93d9c897e --- /dev/null +++ b/vsprojects/vcxproj/check_epollexclusive/check_epollexclusive.vcxproj.filters @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="$(SolutionDir)\..\test\build\check_epollexclusive.c"> + <Filter>test\build</Filter> + </ClCompile> + </ItemGroup> + + <ItemGroup> + <Filter Include="test"> + <UniqueIdentifier>{98195cc4-af1b-3ef2-80a8-86b96fa1c488}</UniqueIdentifier> + </Filter> + <Filter Include="test\build"> + <UniqueIdentifier>{c32fe5ee-bf78-58e4-fa70-b9294e48a136}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project> + diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj index 32d2e09a588e90c45cc377a2ac902222c0dbde21..f8fae96d90295771afa25d7934d22dfce4c7e933 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj @@ -386,7 +386,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" /> @@ -396,7 +395,11 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" /> @@ -405,6 +408,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" /> @@ -426,6 +430,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" /> @@ -437,6 +442,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" /> @@ -482,6 +488,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" /> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" /> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" /> @@ -588,8 +595,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c"> @@ -610,7 +615,15 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> </ClCompile> @@ -630,6 +643,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c"> @@ -702,6 +717,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c"> @@ -810,6 +827,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c"> diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters index a3346bc29795ffe2ef945823aa86e1acae1aa14e..73353752b5fa740a300e1e55e4b5ed20ed066137 100644 --- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters @@ -151,9 +151,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> <Filter>src\core\lib\compression</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - <Filter>src\core\lib\debug</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> <Filter>src\core\lib\http</Filter> </ClCompile> @@ -184,7 +181,19 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> @@ -214,6 +223,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -322,6 +334,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -484,6 +499,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> <Filter>src\core\lib\transport</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + <Filter>src\core\lib\debug</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c"> <Filter>third_party\nanopb</Filter> </ClCompile> @@ -878,9 +896,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h"> <Filter>src\core\lib\compression</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> - <Filter>src\core\lib\debug</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h"> <Filter>src\core\lib\http</Filter> </ClInclude> @@ -908,7 +923,19 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h"> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h"> @@ -935,6 +962,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -998,6 +1028,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -1031,6 +1064,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -1166,6 +1202,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h"> <Filter>src\core\lib\transport</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> + <Filter>src\core\lib\debug</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h"> <Filter>third_party\nanopb</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj index 28ccefc651c817bedd83e604ad0492dbd73f5111..02e3399f0528b4fcc9e694e6e2b8ce93a73917ce 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj @@ -380,7 +380,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" /> @@ -390,7 +389,11 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" /> @@ -399,6 +402,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" /> @@ -420,6 +424,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" /> @@ -431,6 +436,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" /> @@ -476,6 +482,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" /> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_common.h" /> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.h" /> @@ -572,8 +579,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c"> @@ -594,7 +599,15 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> </ClCompile> @@ -614,6 +627,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c"> @@ -686,6 +701,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c"> @@ -794,6 +811,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_decode.c"> diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters index 83f869dab36bcdc1f0b2e662ef5bff2028ddffee..5d7f082fdd197560d8bb5e81845782b4374e6002 100644 --- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters @@ -136,9 +136,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> <Filter>src\core\lib\compression</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - <Filter>src\core\lib\debug</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> <Filter>src\core\lib\http</Filter> </ClCompile> @@ -169,7 +166,19 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> @@ -199,6 +208,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -307,6 +319,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -469,6 +484,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> <Filter>src\core\lib\transport</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + <Filter>src\core\lib\debug</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\third_party\nanopb\pb_common.c"> <Filter>third_party\nanopb</Filter> </ClCompile> @@ -845,9 +863,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h"> <Filter>src\core\lib\compression</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> - <Filter>src\core\lib\debug</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h"> <Filter>src\core\lib\http</Filter> </ClInclude> @@ -875,7 +890,19 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h"> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h"> @@ -902,6 +929,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -965,6 +995,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -998,6 +1031,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -1133,6 +1169,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h"> <Filter>src\core\lib\transport</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> + <Filter>src\core\lib\debug</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h"> <Filter>third_party\nanopb</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 94c2efed8fee087752f5e2ed9bfa00f122d8a4dc..28ef1042c86cee2567351717ef50ab06139641cd 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -310,7 +310,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" /> @@ -320,7 +319,11 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" /> @@ -329,6 +332,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" /> @@ -350,6 +354,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" /> @@ -361,6 +366,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" /> @@ -406,6 +412,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" /> @@ -531,8 +538,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c"> @@ -553,7 +558,15 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> </ClCompile> @@ -573,6 +586,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c"> @@ -645,6 +660,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c"> @@ -753,6 +770,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\secure\server_secure_chttp2.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.c"> diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index 5f11b64c971a3e9998d80a303b6a0b92e310f6cd..176bd47e741bab86990e1d4ab0c21278e93359cc 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -31,9 +31,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> <Filter>src\core\lib\compression</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - <Filter>src\core\lib\debug</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> <Filter>src\core\lib\http</Filter> </ClCompile> @@ -64,7 +61,19 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> @@ -94,6 +103,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -202,6 +214,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -364,6 +379,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> <Filter>src\core\lib\transport</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + <Filter>src\core\lib\debug</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\secure\server_secure_chttp2.c"> <Filter>src\core\ext\transport\chttp2\server\secure</Filter> </ClCompile> @@ -851,9 +869,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h"> <Filter>src\core\lib\compression</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> - <Filter>src\core\lib\debug</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h"> <Filter>src\core\lib\http</Filter> </ClInclude> @@ -881,7 +896,19 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h"> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h"> @@ -908,6 +935,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -971,6 +1001,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -1004,6 +1037,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -1139,6 +1175,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h"> <Filter>src\core\lib\transport</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> + <Filter>src\core\lib\debug</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h"> <Filter>src\core\ext\transport\chttp2\transport</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj index df89932a97c3ea326a36c9817a5c6d99def5cf57..2f245d55584c0f9fbf65720c3365fdbd7d22417a 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj @@ -205,7 +205,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" /> @@ -215,7 +214,11 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" /> @@ -224,6 +227,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" /> @@ -245,6 +249,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" /> @@ -256,6 +261,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" /> @@ -301,6 +307,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\data\client_certs.c"> @@ -361,8 +368,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c"> @@ -383,7 +388,15 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> </ClCompile> @@ -403,6 +416,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c"> @@ -475,6 +490,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c"> @@ -583,6 +600,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + </ClCompile> </ItemGroup> <ItemGroup> <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj"> diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters index 22cfbe14d4dd5a0ecb635eacb4befdecdb7b8724..d2caf223a5e2c2ee9d2e668330f109ea8611e8ed 100644 --- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters @@ -88,9 +88,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> <Filter>src\core\lib\compression</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - <Filter>src\core\lib\debug</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> <Filter>src\core\lib\http</Filter> </ClCompile> @@ -121,7 +118,19 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> @@ -151,6 +160,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -259,6 +271,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -421,6 +436,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> <Filter>src\core\lib\transport</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + <Filter>src\core\lib\debug</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="$(SolutionDir)\..\include\grpc\byte_buffer.h"> @@ -593,9 +611,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h"> <Filter>src\core\lib\compression</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> - <Filter>src\core\lib\debug</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h"> <Filter>src\core\lib\http</Filter> </ClInclude> @@ -623,7 +638,19 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h"> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h"> @@ -650,6 +677,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -713,6 +743,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -746,6 +779,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -881,6 +917,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h"> <Filter>src\core\lib\transport</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> + <Filter>src\core\lib\debug</Filter> + </ClInclude> </ItemGroup> <ItemGroup> diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 9592ee39e7db3874198e6ce7652727922e5b15e3..98d690d7f98e5617092910b3f3a11443de116272 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -300,7 +300,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\httpcli.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\parser.h" /> @@ -310,7 +309,11 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\endpoint_pair.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h" /> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\exec_ctx.h" /> @@ -319,6 +322,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_internal.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\network_status_tracker.h" /> @@ -340,6 +344,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_utils_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client_posix.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_posix.h" /> @@ -351,6 +356,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_generic.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\unix_sockets_posix.h" /> @@ -396,6 +402,7 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\timeout_encoding.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h" /> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_encoder.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\chttp2_transport.h" /> @@ -498,8 +505,6 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\httpcli.c"> @@ -520,7 +525,15 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> </ClCompile> @@ -540,6 +553,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\lockfree_event.c"> @@ -612,6 +627,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\udp_server.c"> @@ -720,6 +737,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2_posix.c"> diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index b12d596beb87a23099e8a9987181f39c473cc2cb..a2dddf643a03d2c64a8e8d5c1155a8e1b40e8f1d 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -34,9 +34,6 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c"> <Filter>src\core\lib\compression</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> - <Filter>src\core\lib\debug</Filter> - </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\http\format_request.c"> <Filter>src\core\lib\http</Filter> </ClCompile> @@ -67,7 +64,19 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\error.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> - <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.c"> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.c"> @@ -97,6 +106,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_windows.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -205,6 +217,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.c"> + <Filter>src\core\lib\iomgr</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.c"> <Filter>src\core\lib\iomgr</Filter> </ClCompile> @@ -367,6 +382,9 @@ <ClCompile Include="$(SolutionDir)\..\src\core\lib\transport\transport_op_string.c"> <Filter>src\core\lib\transport</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\src\core\lib\debug\trace.c"> + <Filter>src\core\lib\debug</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\server\insecure\server_chttp2.c"> <Filter>src\core\ext\transport\chttp2\server\insecure</Filter> </ClCompile> @@ -761,9 +779,6 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h"> <Filter>src\core\lib\compression</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> - <Filter>src\core\lib\debug</Filter> - </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\http\format_request.h"> <Filter>src\core\lib\http</Filter> </ClInclude> @@ -791,7 +806,19 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\error_internal.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> - <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_linux.h"> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll1_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_limited_pollers_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epoll_thread_pool_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollex_linux.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_epollsig_linux.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\ev_poll_posix.h"> @@ -818,6 +845,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\iomgr_posix.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\is_epollexclusive_available.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\load_file.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -881,6 +911,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\socket_windows.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\sys_epoll_wrapper.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\tcp_client.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -914,6 +947,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_heap.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_manager.h"> + <Filter>src\core\lib\iomgr</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\lib\iomgr\timer_uv.h"> <Filter>src\core\lib\iomgr</Filter> </ClInclude> @@ -1049,6 +1085,9 @@ <ClInclude Include="$(SolutionDir)\..\src\core\lib\transport\transport_impl.h"> <Filter>src\core\lib\transport</Filter> </ClInclude> + <ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h"> + <Filter>src\core\lib\debug</Filter> + </ClInclude> <ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\transport\bin_decoder.h"> <Filter>src\core\ext\transport\chttp2\transport</Filter> </ClInclude> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj index e3adf793d63f936ebb393c3e24bc61c4a2298801..8581f0cb374ed18b2d8eb39f90a8c9a602cdbdac 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj @@ -255,6 +255,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\trailing_metadata.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\workaround_cronet_compression.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\write_buffering.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\write_buffering_at_end.c"> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters index cfb8d043baf4a9369c606f38f9106ccaa20e675e..ae2937b1b9e14dfec10112dab300e2dcdbbcff5d 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_nosec_tests/end2end_nosec_tests.vcxproj.filters @@ -157,6 +157,9 @@ <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\trailing_metadata.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\workaround_cronet_compression.c"> + <Filter>test\core\end2end\tests</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\write_buffering.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj index a67f509e25564929b76bcb05ca11995372aadb69..1bd09989e89f3ba6955d91db1189c3da42ea0368 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj @@ -257,6 +257,8 @@ </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\trailing_metadata.c"> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\workaround_cronet_compression.c"> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\write_buffering.c"> </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\write_buffering_at_end.c"> diff --git a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters index 97ba77a42e12a70ed9ce1a8d9cae758d5b50b45d..217c60ee0524ba8902ab6c52f06c6a8625ec8b7c 100644 --- a/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters +++ b/vsprojects/vcxproj/test/end2end/tests/end2end_tests/end2end_tests.vcxproj.filters @@ -160,6 +160,9 @@ <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\trailing_metadata.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile> + <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\workaround_cronet_compression.c"> + <Filter>test\core\end2end\tests</Filter> + </ClCompile> <ClCompile Include="$(SolutionDir)\..\test\core\end2end\tests\write_buffering.c"> <Filter>test\core\end2end\tests</Filter> </ClCompile>