diff --git a/.gitmodules b/.gitmodules index 06f1394df65..f4690a2687f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -50,7 +50,7 @@ url = https://github.com/googleapis/googleapis.git [submodule "third_party/protoc-gen-validate"] path = third_party/protoc-gen-validate - url = https://github.com/lyft/protoc-gen-validate.git + url = https://github.com/envoyproxy/protoc-gen-validate.git [submodule "third_party/upb"] path = third_party/upb url = https://github.com/google/upb.git diff --git a/BUILD b/BUILD index 349ade626b4..8837ed8075f 100644 --- a/BUILD +++ b/BUILD @@ -74,11 +74,11 @@ config_setting( ) # This should be updated along with build.yaml -g_stands_for = "godric" +g_stands_for = "gandalf" core_version = "7.0.0" -version = "1.20.0-dev" +version = "1.21.0-dev" GPR_PUBLIC_HDRS = [ "include/grpc/support/alloc.h", @@ -192,8 +192,8 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpc++/impl/service_type.h", "include/grpc++/impl/sync_cxx11.h", "include/grpc++/impl/sync_no_cxx11.h", - "include/grpc++/resource_quota.h", "include/grpc++/security/auth_context.h", + "include/grpc++/resource_quota.h", "include/grpc++/security/auth_metadata_processor.h", "include/grpc++/security/credentials.h", "include/grpc++/security/server_credentials.h", @@ -219,12 +219,16 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", @@ -235,20 +239,27 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/impl/sync_cxx11.h", "include/grpcpp/impl/sync_no_cxx11.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", + "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", + "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", @@ -307,7 +318,6 @@ grpc_cc_library( public_hdrs = GRPC_PUBLIC_HDRS + GRPC_SECURE_PUBLIC_HDRS, standalone = True, deps = [ - "grpc_cfstream", "grpc_common", "grpc_lb_policy_grpclb_secure", "grpc_lb_policy_xds_secure", @@ -361,7 +371,6 @@ grpc_cc_library( "gpr", "grpc", "grpc++_base", - "grpc_cfstream", "grpc++_codegen_base", "grpc++_codegen_base_src", "grpc++_codegen_proto", @@ -395,6 +404,7 @@ grpc_cc_library( hdrs = [ "include/grpc++/support/error_details.h", "include/grpcpp/support/error_details.h", + "include/grpcpp/support/error_details_impl.h", ], language = "c++", standalone = True, @@ -578,8 +588,10 @@ grpc_cc_library( "src/core/lib/gprpp/abstract.h", "src/core/lib/gprpp/fork.h", "src/core/lib/gprpp/manual_constructor.h", + "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", "src/core/lib/gprpp/mutex_lock.h", + "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h", ], @@ -725,12 +737,15 @@ grpc_cc_library( "src/core/lib/http/parser.cc", "src/core/lib/iomgr/buffer_list.cc", "src/core/lib/iomgr/call_combiner.cc", + "src/core/lib/iomgr/cfstream_handle.cc", "src/core/lib/iomgr/combiner.cc", "src/core/lib/iomgr/endpoint.cc", + "src/core/lib/iomgr/endpoint_cfstream.cc", "src/core/lib/iomgr/endpoint_pair_posix.cc", "src/core/lib/iomgr/endpoint_pair_uv.cc", "src/core/lib/iomgr/endpoint_pair_windows.cc", "src/core/lib/iomgr/error.cc", + "src/core/lib/iomgr/error_cfstream.cc", "src/core/lib/iomgr/ev_epoll1_linux.cc", "src/core/lib/iomgr/ev_epollex_linux.cc", "src/core/lib/iomgr/ev_poll_posix.cc", @@ -751,6 +766,7 @@ grpc_cc_library( "src/core/lib/iomgr/iomgr_custom.cc", "src/core/lib/iomgr/iomgr_internal.cc", "src/core/lib/iomgr/iomgr_posix.cc", + "src/core/lib/iomgr/iomgr_posix_cfstream.cc", "src/core/lib/iomgr/iomgr_windows.cc", "src/core/lib/iomgr/is_epollexclusive_available.cc", "src/core/lib/iomgr/load_file.cc", @@ -777,6 +793,7 @@ grpc_cc_library( "src/core/lib/iomgr/socket_utils_windows.cc", "src/core/lib/iomgr/socket_windows.cc", "src/core/lib/iomgr/tcp_client.cc", + "src/core/lib/iomgr/tcp_client_cfstream.cc", "src/core/lib/iomgr/tcp_client_custom.cc", "src/core/lib/iomgr/tcp_client_posix.cc", "src/core/lib/iomgr/tcp_client_windows.cc", @@ -876,12 +893,15 @@ grpc_cc_library( "src/core/lib/iomgr/block_annotate.h", "src/core/lib/iomgr/buffer_list.h", "src/core/lib/iomgr/call_combiner.h", + "src/core/lib/iomgr/cfstream_handle.h", "src/core/lib/iomgr/closure.h", "src/core/lib/iomgr/combiner.h", "src/core/lib/iomgr/dynamic_annotations.h", "src/core/lib/iomgr/endpoint.h", + "src/core/lib/iomgr/endpoint_cfstream.h", "src/core/lib/iomgr/endpoint_pair.h", "src/core/lib/iomgr/error.h", + "src/core/lib/iomgr/error_cfstream.h", "src/core/lib/iomgr/error_internal.h", "src/core/lib/iomgr/ev_epoll1_linux.h", "src/core/lib/iomgr/ev_epollex_linux.h", @@ -1036,27 +1056,6 @@ grpc_cc_library( ], ) -grpc_cc_library( - name = "grpc_cfstream", - srcs = [ - "src/core/lib/iomgr/cfstream_handle.cc", - "src/core/lib/iomgr/endpoint_cfstream.cc", - "src/core/lib/iomgr/error_cfstream.cc", - "src/core/lib/iomgr/iomgr_posix_cfstream.cc", - "src/core/lib/iomgr/tcp_client_cfstream.cc", - ], - hdrs = [ - "src/core/lib/iomgr/cfstream_handle.h", - "src/core/lib/iomgr/endpoint_cfstream.h", - "src/core/lib/iomgr/error_cfstream.h", - ], - use_cfstream = True, - deps = [ - ":gpr_base", - ":grpc_base", - ], -) - grpc_cc_library( name = "grpc_client_channel", srcs = [ @@ -1476,6 +1475,7 @@ grpc_cc_library( language = "c++", public_hdrs = [ "include/grpcpp/ext/server_load_reporting.h", + "include/grpcpp/ext/server_load_reporting_impl.h", ], deps = [ "lb_server_load_reporting_filter", @@ -2200,6 +2200,7 @@ grpc_cc_library( public_hdrs = [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", ], deps = [ ":grpc++", @@ -2220,6 +2221,7 @@ grpc_cc_library( language = "c++", public_hdrs = [ "include/grpcpp/ext/channelz_service_plugin.h", + "include/grpcpp/ext/channelz_service_plugin_impl.h", ], deps = [ ":grpc++", @@ -2284,6 +2286,7 @@ grpc_cc_library( ], hdrs = [ "include/grpcpp/opencensus.h", + "include/grpcpp/opencensus_impl.h", "src/cpp/ext/filters/census/channel_filter.h", "src/cpp/ext/filters/census/client_filter.h", "src/cpp/ext/filters/census/context.h", @@ -2313,38 +2316,60 @@ grpc_cc_library( ) #TODO: Get this into build.yaml once we start using it. +grpc_cc_library( + name = "envoy_lrs_upb", + srcs = [ + "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c", + "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c", + ], + hdrs = [ + "src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h", + "src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h", + ], + language = "c++", + external_deps = [ + "upb_lib", + ], + deps = [ + ":envoy_core_upb", + ":google_api_upb", + ":proto_gen_validate_upb", + ] +) + grpc_cc_library( name = "envoy_ads_upb", srcs = [ "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.c", + "src/core/ext/upb-generated/envoy/api/v2/cds.upb.c", "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.c", "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.c", "src/core/ext/upb-generated/envoy/api/v2/discovery.upb.c", - "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c", - "src/core/ext/upb-generated/envoy/api/v2/cds.upb.c", "src/core/ext/upb-generated/envoy/api/v2/eds.upb.c", + "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.c", "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.c", ], hdrs = [ "src/core/ext/upb-generated/envoy/api/v2/auth/cert.upb.h", + "src/core/ext/upb-generated/envoy/api/v2/cds.upb.h", "src/core/ext/upb-generated/envoy/api/v2/cluster/circuit_breaker.upb.h", "src/core/ext/upb-generated/envoy/api/v2/cluster/outlier_detection.upb.h", "src/core/ext/upb-generated/envoy/api/v2/discovery.upb.h", - "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h", - "src/core/ext/upb-generated/envoy/api/v2/cds.upb.h", "src/core/ext/upb-generated/envoy/api/v2/eds.upb.h", + "src/core/ext/upb-generated/envoy/api/v2/endpoint/endpoint.upb.h", "src/core/ext/upb-generated/envoy/service/discovery/v2/ads.upb.h", ], - language = "c++", external_deps = [ "upb_lib", ], + language = "c++", deps = [ ":envoy_core_upb", ":envoy_type_upb", ":google_api_upb", ":proto_gen_validate_upb", - ] + ], + tags = ["no_windows"], ) grpc_cc_library( @@ -2365,15 +2390,16 @@ grpc_cc_library( "src/core/ext/upb-generated/envoy/api/v2/core/health_check.upb.h", "src/core/ext/upb-generated/envoy/api/v2/core/protocol.upb.h", ], - language = "c++", external_deps = [ "upb_lib", ], + language = "c++", + tags = ["no_windows"], deps = [ ":envoy_type_upb", ":google_api_upb", - ":proto_gen_validate_upb" - ] + ":proto_gen_validate_upb", + ], ) grpc_cc_library( @@ -2386,14 +2412,15 @@ grpc_cc_library( "src/core/ext/upb-generated/envoy/type/percent.upb.h", "src/core/ext/upb-generated/envoy/type/range.upb.h", ], - language = "c++", external_deps = [ "upb_lib", ], + language = "c++", + tags = ["no_windows"], deps = [ ":google_api_upb", - ":proto_gen_validate_upb" - ] + ":proto_gen_validate_upb", + ], ) grpc_cc_library( @@ -2406,13 +2433,14 @@ grpc_cc_library( "src/core/ext/upb-generated/gogoproto/gogo.upb.h", "src/core/ext/upb-generated/validate/validate.upb.h", ], - language = "c++", external_deps = [ "upb_lib", ], + language = "c++", + tags = ["no_windows"], deps = [ ":google_api_upb", - ] + ], ) grpc_cc_library( @@ -2441,10 +2469,19 @@ grpc_cc_library( "src/core/ext/upb-generated/google/protobuf/wrappers.upb.h", "src/core/ext/upb-generated/google/rpc/status.upb.h", ], - language = "c++", external_deps = [ "upb_lib", ], + language = "c++", + tags = ["no_windows"], ) grpc_generate_one_off_targets() + +filegroup( + name = "root_certificates", + srcs = [ + "etc/roots.pem", + ], + visibility = ["//visibility:public"], +) diff --git a/BUILD.gn b/BUILD.gn index d15961a4879..1417f1db5ea 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -184,8 +184,10 @@ config("grpc_config") { "src/core/lib/gprpp/fork.cc", "src/core/lib/gprpp/fork.h", "src/core/lib/gprpp/manual_constructor.h", + "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", "src/core/lib/gprpp/mutex_lock.h", + "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/thd_posix.cc", "src/core/lib/gprpp/thd_windows.cc", @@ -1004,12 +1006,16 @@ config("grpc_config") { "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", @@ -1066,18 +1072,25 @@ config("grpc_config") { "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", + "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", + "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", @@ -1143,10 +1156,12 @@ config("grpc_config") { "src/core/lib/gprpp/fork.h", "src/core/lib/gprpp/inlined_vector.h", "src/core/lib/gprpp/manual_constructor.h", + "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", "src/core/lib/gprpp/mutex_lock.h", "src/core/lib/gprpp/optional.h", "src/core/lib/gprpp/orphanable.h", + "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/ref_counted.h", "src/core/lib/gprpp/ref_counted_ptr.h", "src/core/lib/gprpp/thd.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index e7857d5d84e..5b99a57633a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.20.0-dev") +set(PACKAGE_VERSION "1.21.0-dev") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") @@ -631,6 +631,7 @@ add_dependencies(buildtests_cxx generic_end2end_test) add_dependencies(buildtests_cxx golden_file_test) add_dependencies(buildtests_cxx grpc_alts_credentials_options_test) add_dependencies(buildtests_cxx grpc_cli) +add_dependencies(buildtests_cxx grpc_core_map_test) add_dependencies(buildtests_cxx grpc_linux_system_roots_test) add_dependencies(buildtests_cxx grpc_tool_test) add_dependencies(buildtests_cxx grpclb_api_test) @@ -698,6 +699,7 @@ add_dependencies(buildtests_cxx server_crash_test_client) add_dependencies(buildtests_cxx server_early_return_test) add_dependencies(buildtests_cxx server_interceptors_end2end_test) add_dependencies(buildtests_cxx server_request_call_test) +add_dependencies(buildtests_cxx service_config_test) add_dependencies(buildtests_cxx shutdown_test) add_dependencies(buildtests_cxx slice_hash_table_test) add_dependencies(buildtests_cxx slice_weak_hash_table_test) @@ -2999,12 +3001,16 @@ foreach(_hdr include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h + include/grpcpp/create_channel_impl.h include/grpcpp/create_channel_posix.h + include/grpcpp/create_channel_posix_impl.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h + include/grpcpp/health_check_service_interface_impl.h include/grpcpp/impl/call.h include/grpcpp/impl/channel_argument_option.h include/grpcpp/impl/client_unary_call.h @@ -3015,18 +3021,25 @@ foreach(_hdr include/grpcpp/impl/rpc_service_method.h include/grpcpp/impl/serialization_traits.h include/grpcpp/impl/server_builder_option.h + include/grpcpp/impl/server_builder_option_impl.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h + include/grpcpp/impl/server_initializer_impl.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h + include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h + include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h include/grpcpp/server_posix.h + include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -3590,12 +3603,16 @@ foreach(_hdr include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h + include/grpcpp/create_channel_impl.h include/grpcpp/create_channel_posix.h + include/grpcpp/create_channel_posix_impl.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h + include/grpcpp/health_check_service_interface_impl.h include/grpcpp/impl/call.h include/grpcpp/impl/channel_argument_option.h include/grpcpp/impl/client_unary_call.h @@ -3606,18 +3623,25 @@ foreach(_hdr include/grpcpp/impl/rpc_service_method.h include/grpcpp/impl/serialization_traits.h include/grpcpp/impl/server_builder_option.h + include/grpcpp/impl/server_builder_option_impl.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h + include/grpcpp/impl/server_initializer_impl.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h + include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h + include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h include/grpcpp/server_posix.h + include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -3825,6 +3849,7 @@ target_link_libraries(grpc++_error_details foreach(_hdr include/grpc++/support/error_details.h include/grpcpp/support/error_details.h + include/grpcpp/support/error_details_impl.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) @@ -3958,6 +3983,7 @@ target_link_libraries(grpc++_reflection foreach(_hdr include/grpc++/ext/proto_server_reflection_plugin.h include/grpcpp/ext/proto_server_reflection_plugin.h + include/grpcpp/ext/proto_server_reflection_plugin_impl.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) @@ -4553,12 +4579,16 @@ foreach(_hdr include/grpcpp/client_context.h include/grpcpp/completion_queue.h include/grpcpp/create_channel.h + include/grpcpp/create_channel_impl.h include/grpcpp/create_channel_posix.h + include/grpcpp/create_channel_posix_impl.h include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h + include/grpcpp/health_check_service_interface_impl.h include/grpcpp/impl/call.h include/grpcpp/impl/channel_argument_option.h include/grpcpp/impl/client_unary_call.h @@ -4569,18 +4599,25 @@ foreach(_hdr include/grpcpp/impl/rpc_service_method.h include/grpcpp/impl/serialization_traits.h include/grpcpp/impl/server_builder_option.h + include/grpcpp/impl/server_builder_option_impl.h include/grpcpp/impl/server_builder_plugin.h include/grpcpp/impl/server_initializer.h + include/grpcpp/impl/server_initializer_impl.h include/grpcpp/impl/service_type.h include/grpcpp/resource_quota.h + include/grpcpp/resource_quota_impl.h include/grpcpp/security/auth_context.h include/grpcpp/security/auth_metadata_processor.h + include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h + include/grpcpp/server_builder_impl.h include/grpcpp/server_context.h include/grpcpp/server_posix.h + include/grpcpp/server_posix_impl.h include/grpcpp/support/async_stream.h include/grpcpp/support/async_unary_call.h include/grpcpp/support/byte_buffer.h @@ -4965,6 +5002,7 @@ target_link_libraries(grpcpp_channelz foreach(_hdr include/grpcpp/ext/channelz_service_plugin.h + include/grpcpp/ext/channelz_service_plugin_impl.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) @@ -13455,6 +13493,45 @@ target_link_libraries(grpc_cli ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(grpc_core_map_test + test/core/gprpp/map_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(grpc_core_map_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(grpc_core_map_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc++ + grpc + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + + endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_CODEGEN) @@ -15679,6 +15756,45 @@ target_link_libraries(server_request_call_test ) +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(service_config_test + test/core/client_channel/service_config_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + + +target_include_directories(service_config_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} + PRIVATE third_party/googletest/googletest/include + PRIVATE third_party/googletest/googletest + PRIVATE third_party/googletest/googlemock/include + PRIVATE third_party/googletest/googlemock + PRIVATE ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(service_config_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc++ + grpc + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + + endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index c0b277f0fb1..2e6e6070c43 100644 --- a/Makefile +++ b/Makefile @@ -460,8 +460,8 @@ Q = @ endif CORE_VERSION = 7.0.0 -CPP_VERSION = 1.20.0-dev -CSHARP_VERSION = 1.20.0-dev +CPP_VERSION = 1.21.0-dev +CSHARP_VERSION = 1.21.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) @@ -1209,6 +1209,7 @@ generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test grpc_alts_credentials_options_test: $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli +grpc_core_map_test: $(BINDIR)/$(CONFIG)/grpc_core_map_test grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin grpc_linux_system_roots_test: $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test @@ -1261,6 +1262,7 @@ server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client server_early_return_test: $(BINDIR)/$(CONFIG)/server_early_return_test server_interceptors_end2end_test: $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test server_request_call_test: $(BINDIR)/$(CONFIG)/server_request_call_test +service_config_test: $(BINDIR)/$(CONFIG)/service_config_test shutdown_test: $(BINDIR)/$(CONFIG)/shutdown_test slice_hash_table_test: $(BINDIR)/$(CONFIG)/slice_hash_table_test slice_weak_hash_table_test: $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test @@ -1680,6 +1682,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/golden_file_test \ $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test \ $(BINDIR)/$(CONFIG)/grpc_cli \ + $(BINDIR)/$(CONFIG)/grpc_core_map_test \ $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ @@ -1725,6 +1728,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/server_early_return_test \ $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \ $(BINDIR)/$(CONFIG)/server_request_call_test \ + $(BINDIR)/$(CONFIG)/service_config_test \ $(BINDIR)/$(CONFIG)/shutdown_test \ $(BINDIR)/$(CONFIG)/slice_hash_table_test \ $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test \ @@ -1821,6 +1825,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/golden_file_test \ $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test \ $(BINDIR)/$(CONFIG)/grpc_cli \ + $(BINDIR)/$(CONFIG)/grpc_core_map_test \ $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ @@ -1866,6 +1871,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/server_early_return_test \ $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test \ $(BINDIR)/$(CONFIG)/server_request_call_test \ + $(BINDIR)/$(CONFIG)/service_config_test \ $(BINDIR)/$(CONFIG)/shutdown_test \ $(BINDIR)/$(CONFIG)/slice_hash_table_test \ $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test \ @@ -2311,6 +2317,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_alts_credentials_options_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test || ( echo test grpc_alts_credentials_options_test failed ; exit 1 ) + $(E) "[RUN] Testing grpc_core_map_test" + $(Q) $(BINDIR)/$(CONFIG)/grpc_core_map_test || ( echo test grpc_core_map_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_linux_system_roots_test" $(Q) $(BINDIR)/$(CONFIG)/grpc_linux_system_roots_test || ( echo test grpc_linux_system_roots_test failed ; exit 1 ) $(E) "[RUN] Testing grpc_tool_test" @@ -2377,6 +2385,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/server_interceptors_end2end_test || ( echo test server_interceptors_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing server_request_call_test" $(Q) $(BINDIR)/$(CONFIG)/server_request_call_test || ( echo test server_request_call_test failed ; exit 1 ) + $(E) "[RUN] Testing service_config_test" + $(Q) $(BINDIR)/$(CONFIG)/service_config_test || ( echo test service_config_test failed ; exit 1 ) $(E) "[RUN] Testing shutdown_test" $(Q) $(BINDIR)/$(CONFIG)/shutdown_test || ( echo test shutdown_test failed ; exit 1 ) $(E) "[RUN] Testing slice_hash_table_test" @@ -5326,12 +5336,16 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ + include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ + include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ + include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -5342,18 +5356,25 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ + include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ + include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ + include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ + include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ + include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -5925,12 +5946,16 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ + include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ + include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ + include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -5941,18 +5966,25 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ + include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ + include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ + include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ + include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ + include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -6166,6 +6198,7 @@ LIBGRPC++_ERROR_DETAILS_SRC = \ PUBLIC_HEADERS_CXX += \ include/grpc++/support/error_details.h \ include/grpcpp/support/error_details.h \ + include/grpcpp/support/error_details_impl.h \ LIBGRPC++_ERROR_DETAILS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_ERROR_DETAILS_SRC)))) @@ -6292,6 +6325,7 @@ LIBGRPC++_REFLECTION_SRC = \ PUBLIC_HEADERS_CXX += \ include/grpc++/ext/proto_server_reflection_plugin.h \ include/grpcpp/ext/proto_server_reflection_plugin.h \ + include/grpcpp/ext/proto_server_reflection_plugin_impl.h \ LIBGRPC++_REFLECTION_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_REFLECTION_SRC)))) @@ -6837,12 +6871,16 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ + include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ + include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ + include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -6853,18 +6891,25 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ + include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ + include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ + include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ + include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ + include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ + include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -7218,6 +7263,7 @@ LIBGRPCPP_CHANNELZ_SRC = \ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/channelz_service_plugin.h \ + include/grpcpp/ext/channelz_service_plugin_impl.h \ LIBGRPCPP_CHANNELZ_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPCPP_CHANNELZ_SRC)))) @@ -16421,6 +16467,49 @@ endif endif +GRPC_CORE_MAP_TEST_SRC = \ + test/core/gprpp/map_test.cc \ + +GRPC_CORE_MAP_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_CORE_MAP_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpc_core_map_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/grpc_core_map_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpc_core_map_test: $(PROTOBUF_DEP) $(GRPC_CORE_MAP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(GRPC_CORE_MAP_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_core_map_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/core/gprpp/map_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpc_core_map_test: $(GRPC_CORE_MAP_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPC_CORE_MAP_TEST_OBJS:.o=.dep) +endif +endif + + GRPC_CPP_PLUGIN_SRC = \ src/compiler/cpp_plugin.cc \ @@ -18601,6 +18690,49 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/server/server_request_call_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc +SERVICE_CONFIG_TEST_SRC = \ + test/core/client_channel/service_config_test.cc \ + +SERVICE_CONFIG_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVICE_CONFIG_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/service_config_test: openssl_dep_error + +else + + + + +ifeq ($(NO_PROTOBUF),true) + +# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+. + +$(BINDIR)/$(CONFIG)/service_config_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/service_config_test: $(PROTOBUF_DEP) $(SERVICE_CONFIG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(SERVICE_CONFIG_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/service_config_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/test/core/client_channel/service_config_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_service_config_test: $(SERVICE_CONFIG_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(SERVICE_CONFIG_TEST_OBJS:.o=.dep) +endif +endif + + SHUTDOWN_TEST_SRC = \ test/cpp/end2end/shutdown_test.cc \ diff --git a/WORKSPACE b/WORKSPACE index 81371bf4187..b984438d1d6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -11,26 +11,21 @@ grpc_test_only_deps() register_execution_platforms( "//third_party/toolchains:rbe_ubuntu1604", "//third_party/toolchains:rbe_ubuntu1604_large", + "//third_party/toolchains:rbe_windows", ) register_toolchains( "//third_party/toolchains:cc-toolchain-clang-x86_64-default", + "//third_party/toolchains/bazel_0.23.2_rbe_windows:cc-toolchain-x64_windows", ) -http_archive( - name = "cython", - build_file = "//third_party:cython.BUILD", - sha256 = "d68138a2381afbdd0876c3cb2a22389043fa01c4badede1228ee073032b07a27", - strip_prefix = "cython-c2b80d87658a8525ce091cbe146cb7eaa29fed5c", - urls = [ - "https://github.com/cython/cython/archive/c2b80d87658a8525ce091cbe146cb7eaa29fed5c.tar.gz", - ], +# TODO(https://github.com/grpc/grpc/issues/18331): Move off of this dependency. +git_repository( + name = "org_pubref_rules_protobuf", + remote = "https://github.com/ghostwriternr/rules_protobuf", + tag = "v0.8.2.1-alpha", ) -load("//third_party/py:python_configure.bzl", "python_configure") - -python_configure(name = "local_config_python") - git_repository( name = "io_bazel_rules_python", commit = "8b5d0683a7d878b28fffe464779c8a53659fc645", @@ -39,24 +34,21 @@ git_repository( load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import") -pip_repositories() - pip_import( name = "grpc_python_dependencies", requirements = "//:requirements.bazel.txt", ) -load("@grpc_python_dependencies//:requirements.bzl", "pip_install") - -pip_install() - -# NOTE(https://github.com/pubref/rules_protobuf/pull/196): Switch to upstream repo after this gets merged. -git_repository( - name = "org_pubref_rules_protobuf", - remote = "https://github.com/ghostwriternr/rules_protobuf", - tag = "v0.8.2.1-alpha", +http_archive( + name = "cython", + build_file = "//third_party:cython.BUILD", + sha256 = "d68138a2381afbdd0876c3cb2a22389043fa01c4badede1228ee073032b07a27", + strip_prefix = "cython-c2b80d87658a8525ce091cbe146cb7eaa29fed5c", + urls = [ + "https://github.com/cython/cython/archive/c2b80d87658a8525ce091cbe146cb7eaa29fed5c.tar.gz", + ], ) -load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") +load("//bazel:grpc_python_deps.bzl", "grpc_python_deps") -py_proto_repositories() +grpc_python_deps() diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index 2a09022c64c..bc4d1f1358a 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -80,7 +80,8 @@ def grpc_cc_library( visibility = None, alwayslink = 0, data = [], - use_cfstream = False): + use_cfstream = False, + tags = []): copts = [] if use_cfstream: copts = if_mac(["-DGRPC_CFSTREAM"]) @@ -117,6 +118,7 @@ def grpc_cc_library( ], alwayslink = alwayslink, data = data, + tags = tags, ) def grpc_proto_plugin(name, srcs = [], deps = []): @@ -149,7 +151,6 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data if language.upper() == "C": copts = copts + if_not_windows(["-std=c99"]) args = { - "name": name, "srcs": srcs, "args": args, "data": data, @@ -161,7 +162,17 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data "exec_compatible_with": exec_compatible_with, } if uses_polling: - native.cc_test(testonly = True, tags = ["manual"], **args) + # Only run targets with pollers for non-MSVC + # TODO(yfen): Enable MSVC for poller-enabled targets without pollers + native.cc_test( + name = name, + testonly = True, + tags = [ + "manual", + "no_windows", + ], + **args + ) for poller in POLLERS: native.sh_test( name = name + "@poller=" + poller, @@ -175,13 +186,13 @@ def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data poller, "$(location %s)" % name, ] + args["args"], - tags = tags, + tags = (tags + ["no_windows"]), exec_compatible_with = exec_compatible_with, ) else: - native.cc_test(**args) + native.cc_test(tags = tags, **args) -def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = []): +def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], data = [], language = "C++", testonly = False, linkshared = False, linkopts = [], tags = []): copts = [] if language.upper() == "C": copts = ["-std=c99"] @@ -195,6 +206,7 @@ def grpc_cc_binary(name, srcs = [], deps = [], external_deps = [], args = [], da deps = deps + _get_external_deps(external_deps), copts = copts, linkopts = if_not_windows(["-pthread"]) + linkopts, + tags = tags, ) def grpc_generate_one_off_targets(): diff --git a/bazel/grpc_python_deps.bzl b/bazel/grpc_python_deps.bzl new file mode 100644 index 00000000000..ec3df19e03a --- /dev/null +++ b/bazel/grpc_python_deps.bzl @@ -0,0 +1,16 @@ +load("//third_party/py:python_configure.bzl", "python_configure") +load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories") +load("@grpc_python_dependencies//:requirements.bzl", "pip_install") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") + +def grpc_python_deps(): + # TODO(https://github.com/grpc/grpc/issues/18256): Remove conditional. + if hasattr(native, "http_archive"): + python_configure(name = "local_config_python") + pip_repositories() + pip_install() + py_proto_repositories() + else: + print("Building Python gRPC with bazel 23.0+ is disabled pending " + + "resolution of https://github.com/grpc/grpc/issues/18256.") + diff --git a/build.yaml b/build.yaml index c1271be9131..5e8c803e56f 100644 --- a/build.yaml +++ b/build.yaml @@ -13,8 +13,8 @@ settings: '#09': Per-language overrides are possible with (eg) ruby_version tag here '#10': See the expand_version.py for all the quirks here core_version: 7.0.0 - g_stands_for: godric - version: 1.20.0-dev + g_stands_for: gandalf + version: 1.21.0-dev filegroups: - name: alts_proto headers: @@ -194,8 +194,10 @@ filegroups: - src/core/lib/gprpp/atomic.h - src/core/lib/gprpp/fork.h - src/core/lib/gprpp/manual_constructor.h + - src/core/lib/gprpp/map.h - src/core/lib/gprpp/memory.h - src/core/lib/gprpp/mutex_lock.h + - src/core/lib/gprpp/pair.h - src/core/lib/gprpp/thd.h - src/core/lib/profiling/timers.h uses: @@ -1344,12 +1346,16 @@ filegroups: - include/grpcpp/client_context.h - include/grpcpp/completion_queue.h - include/grpcpp/create_channel.h + - include/grpcpp/create_channel_impl.h - include/grpcpp/create_channel_posix.h + - include/grpcpp/create_channel_posix_impl.h - include/grpcpp/ext/health_check_service_server_builder_option.h - include/grpcpp/generic/async_generic_service.h - include/grpcpp/generic/generic_stub.h + - include/grpcpp/generic/generic_stub_impl.h - include/grpcpp/grpcpp.h - include/grpcpp/health_check_service_interface.h + - include/grpcpp/health_check_service_interface_impl.h - include/grpcpp/impl/call.h - include/grpcpp/impl/channel_argument_option.h - include/grpcpp/impl/client_unary_call.h @@ -1360,18 +1366,25 @@ filegroups: - include/grpcpp/impl/rpc_service_method.h - include/grpcpp/impl/serialization_traits.h - include/grpcpp/impl/server_builder_option.h + - include/grpcpp/impl/server_builder_option_impl.h - include/grpcpp/impl/server_builder_plugin.h - include/grpcpp/impl/server_initializer.h + - include/grpcpp/impl/server_initializer_impl.h - include/grpcpp/impl/service_type.h - include/grpcpp/resource_quota.h + - include/grpcpp/resource_quota_impl.h - include/grpcpp/security/auth_context.h - include/grpcpp/security/auth_metadata_processor.h + - include/grpcpp/security/auth_metadata_processor_impl.h - include/grpcpp/security/credentials.h - include/grpcpp/security/server_credentials.h + - include/grpcpp/security/server_credentials_impl.h - include/grpcpp/server.h - include/grpcpp/server_builder.h + - include/grpcpp/server_builder_impl.h - include/grpcpp/server_context.h - include/grpcpp/server_posix.h + - include/grpcpp/server_posix_impl.h - include/grpcpp/support/async_stream.h - include/grpcpp/support/async_unary_call.h - include/grpcpp/support/byte_buffer.h @@ -1714,6 +1727,7 @@ libs: public_headers: - include/grpc++/support/error_details.h - include/grpcpp/support/error_details.h + - include/grpcpp/support/error_details_impl.h src: - src/proto/grpc/status/status.proto - src/cpp/util/error_details.cc @@ -1739,6 +1753,7 @@ libs: public_headers: - include/grpc++/ext/proto_server_reflection_plugin.h - include/grpcpp/ext/proto_server_reflection_plugin.h + - include/grpcpp/ext/proto_server_reflection_plugin_impl.h headers: - src/cpp/ext/proto_server_reflection.h src: @@ -1917,6 +1932,7 @@ libs: language: c++ public_headers: - include/grpcpp/ext/channelz_service_plugin.h + - include/grpcpp/ext/channelz_service_plugin_impl.h headers: - src/cpp/server/channelz/channelz_service.h src: @@ -4735,6 +4751,22 @@ targets: - grpc - gpr - grpc++_test_config +- name: grpc_core_map_test + gtest: true + build: test + language: c++ + headers: + - test/core/gprpp/map_tester.h + src: + - test/core/gprpp/map_test.cc + deps: + - grpc_test_util + - grpc++ + - grpc + - gpr + uses: + - grpc++_test + uses_polling: false - name: grpc_cpp_plugin build: protoc language: c++ @@ -5441,6 +5473,19 @@ targets: - grpc++_unsecure - grpc_unsecure - gpr +- name: service_config_test + gtest: true + build: test + language: c++ + src: + - test/core/client_channel/service_config_test.cc + deps: + - grpc_test_util + - grpc++ + - grpc + - gpr + uses: + - grpc++_test - name: shutdown_test gtest: true build: test diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md index a354dad8636..e73e682bbe3 100644 --- a/doc/PROTOCOL-HTTP2.md +++ b/doc/PROTOCOL-HTTP2.md @@ -61,6 +61,8 @@ the form shown above. If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements. +If **Content-Type** does not begin with "application/grpc", gRPC servers SHOULD respond with HTTP status of 415 (Unsupported Media Type). This will prevent other HTTP/2 clients from interpreting a gRPC error response, which uses status 200 (OK), as successful. + **Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**. Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with "-bin". Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received. @@ -255,5 +257,3 @@ to be used. * **Service-Name** → ?( {_proto package name_} "." ) {_service name_} * **Message-Type** → {_fully qualified proto message name_} * **Content-Type** → "application/grpc+proto" - - diff --git a/doc/g_stands_for.md b/doc/g_stands_for.md index 423d8c2fd9a..b926db191de 100644 --- a/doc/g_stands_for.md +++ b/doc/g_stands_for.md @@ -19,4 +19,5 @@ - 1.17 'g' stands for ['gizmo'](https://github.com/grpc/grpc/tree/v1.17.x) - 1.18 'g' stands for ['goose'](https://github.com/grpc/grpc/tree/v1.18.x) - 1.19 'g' stands for ['gold'](https://github.com/grpc/grpc/tree/v1.19.x) -- 1.20 'g' stands for ['godric'](https://github.com/grpc/grpc/tree/master) +- 1.20 'g' stands for ['godric'](https://github.com/grpc/grpc/tree/v1.20.x) +- 1.21 'g' stands for ['gandalf'](https://github.com/grpc/grpc/tree/master) diff --git a/examples/BUILD b/examples/BUILD index 0a1ca94a649..d2b39b87f4d 100644 --- a/examples/BUILD +++ b/examples/BUILD @@ -16,7 +16,9 @@ licenses(["notice"]) # 3-clause BSD package(default_visibility = ["//visibility:public"]) +load("@grpc_python_dependencies//:requirements.bzl", "requirement") load("//bazel:grpc_build_system.bzl", "grpc_proto_library") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_library") grpc_proto_library( name = "auth_sample", @@ -43,60 +45,121 @@ grpc_proto_library( srcs = ["protos/keyvaluestore.proto"], ) +py_proto_library( + name = "py_helloworld", + protos = ["protos/helloworld.proto"], + with_grpc = True, + deps = [requirement('protobuf'),], +) + cc_binary( name = "greeter_client", srcs = ["cpp/helloworld/greeter_client.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], +) + +cc_binary( + name = "greeter_async_client", + srcs = ["cpp/helloworld/greeter_async_client.cc"], + defines = ["BAZEL_BUILD"], + deps = [ + ":helloworld", + "//:grpc++", + ], +) + +cc_binary( + name = "greeter_async_client2", + srcs = ["cpp/helloworld/greeter_async_client2.cc"], + defines = ["BAZEL_BUILD"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "greeter_server", srcs = ["cpp/helloworld/greeter_server.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], +) + +cc_binary( + name = "greeter_async_server", + srcs = ["cpp/helloworld/greeter_async_server.cc"], + defines = ["BAZEL_BUILD"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "metadata_client", srcs = ["cpp/metadata/greeter_client.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "metadata_server", srcs = ["cpp/metadata/greeter_server.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "lb_client", srcs = ["cpp/load_balancing/greeter_client.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "lb_server", srcs = ["cpp/load_balancing/greeter_server.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "compression_client", srcs = ["cpp/compression/greeter_client.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( name = "compression_server", srcs = ["cpp/compression/greeter_server.cc"], defines = ["BAZEL_BUILD"], - deps = [":helloworld", "//:grpc++"], + deps = [ + ":helloworld", + "//:grpc++", + ], ) cc_binary( @@ -104,12 +167,48 @@ cc_binary( srcs = ["cpp/keyvaluestore/caching_interceptor.h", "cpp/keyvaluestore/client.cc"], defines = ["BAZEL_BUILD"], - deps = [":keyvaluestore", "//:grpc++"], + deps = [ + ":keyvaluestore", + "//:grpc++", + ], ) cc_binary( name = "keyvaluestore_server", srcs = ["cpp/keyvaluestore/server.cc"], defines = ["BAZEL_BUILD"], - deps = [":keyvaluestore", "//:grpc++"], -) \ No newline at end of file + deps = [ + ":keyvaluestore", + "//:grpc++", + ], +) + +cc_binary( + name = "route_guide_client", + srcs = [ + "cpp/route_guide/helper.cc", + "cpp/route_guide/helper.h", + "cpp/route_guide/route_guide_client.cc", + ], + data = ["cpp/route_guide/route_guide_db.json"], + defines = ["BAZEL_BUILD"], + deps = [ + ":route_guide", + "//:grpc++", + ], +) + +cc_binary( + name = "route_guide_server", + srcs = [ + "cpp/route_guide/helper.cc", + "cpp/route_guide/helper.h", + "cpp/route_guide/route_guide_server.cc", + ], + data = ["cpp/route_guide/route_guide_db.json"], + defines = ["BAZEL_BUILD"], + deps = [ + ":route_guide", + "//:grpc++", + ], +) diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc index d7a9d52836c..9b1def6d1da 100644 --- a/examples/cpp/helloworld/greeter_async_client.cc +++ b/examples/cpp/helloworld/greeter_async_client.cc @@ -23,7 +23,11 @@ #include #include +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else #include "helloworld.grpc.pb.h" +#endif using grpc::Channel; using grpc::ClientAsyncResponseReader; diff --git a/examples/cpp/helloworld/greeter_async_client2.cc b/examples/cpp/helloworld/greeter_async_client2.cc index d5098b9fc3f..97631f38889 100644 --- a/examples/cpp/helloworld/greeter_async_client2.cc +++ b/examples/cpp/helloworld/greeter_async_client2.cc @@ -24,7 +24,11 @@ #include #include +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else #include "helloworld.grpc.pb.h" +#endif using grpc::Channel; using grpc::ClientAsyncResponseReader; diff --git a/examples/cpp/helloworld/greeter_async_server.cc b/examples/cpp/helloworld/greeter_async_server.cc index a74673d8035..d4d1594c72b 100644 --- a/examples/cpp/helloworld/greeter_async_server.cc +++ b/examples/cpp/helloworld/greeter_async_server.cc @@ -24,7 +24,11 @@ #include #include +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else #include "helloworld.grpc.pb.h" +#endif using grpc::Server; using grpc::ServerAsyncResponseWriter; diff --git a/examples/cpp/route_guide/helper.cc b/examples/cpp/route_guide/helper.cc index 266f754b940..cd889f6a4ba 100644 --- a/examples/cpp/route_guide/helper.cc +++ b/examples/cpp/route_guide/helper.cc @@ -23,7 +23,11 @@ #include #include #include +#ifdef BAZEL_BUILD +#include "examples/protos/route_guide.grpc.pb.h" +#else #include "route_guide.grpc.pb.h" +#endif namespace routeguide { @@ -35,13 +39,16 @@ std::string GetDbFileContent(int argc, char** argv) { size_t start_position = argv_1.find(arg_str); if (start_position != std::string::npos) { start_position += arg_str.size(); - if (argv_1[start_position] == ' ' || - argv_1[start_position] == '=') { + if (argv_1[start_position] == ' ' || argv_1[start_position] == '=') { db_path = argv_1.substr(start_position + 1); } } } else { +#ifdef BAZEL_BUILD + db_path = "cpp/route_guide/route_guide_db.json"; +#else db_path = "route_guide_db.json"; +#endif } std::ifstream db_file(db_path); if (!db_file.is_open()) { @@ -60,17 +67,13 @@ class Parser { public: explicit Parser(const std::string& db) : db_(db) { // Remove all spaces. - db_.erase( - std::remove_if(db_.begin(), db_.end(), isspace), - db_.end()); + db_.erase(std::remove_if(db_.begin(), db_.end(), isspace), db_.end()); if (!Match("[")) { SetFailedAndReturnFalse(); } } - bool Finished() { - return current_ >= db_.size(); - } + bool Finished() { return current_ >= db_.size(); } bool TryParseOne(Feature* feature) { if (failed_ || Finished() || !Match("{")) { @@ -96,7 +99,7 @@ class Parser { if (current_ == db_.size()) { return SetFailedAndReturnFalse(); } - feature->set_name(db_.substr(name_start, current_-name_start-1)); + feature->set_name(db_.substr(name_start, current_ - name_start - 1)); if (!Match("},")) { if (db_[current_ - 1] == ']' && current_ == db_.size()) { return true; @@ -107,7 +110,6 @@ class Parser { } private: - bool SetFailedAndReturnFalse() { failed_ = true; return false; @@ -121,7 +123,8 @@ class Parser { void ReadLong(long* l) { size_t start = current_; - while (current_ != db_.size() && db_[current_] != ',' && db_[current_] != '}') { + while (current_ != db_.size() && db_[current_] != ',' && + db_[current_] != '}') { current_++; } // It will throw an exception if fails. @@ -154,10 +157,8 @@ void ParseDb(const std::string& db, std::vector* feature_list) { break; } } - std::cout << "DB parsed, loaded " << feature_list->size() - << " features." << std::endl; + std::cout << "DB parsed, loaded " << feature_list->size() << " features." + << std::endl; } - } // namespace routeguide - diff --git a/examples/cpp/route_guide/route_guide_client.cc b/examples/cpp/route_guide/route_guide_client.cc index a89ec164c62..439edb0dbdf 100644 --- a/examples/cpp/route_guide/route_guide_client.cc +++ b/examples/cpp/route_guide/route_guide_client.cc @@ -29,7 +29,11 @@ #include #include #include "helper.h" +#ifdef BAZEL_BUILD +#include "examples/protos/route_guide.grpc.pb.h" +#else #include "route_guide.grpc.pb.h" +#endif using grpc::Channel; using grpc::ClientContext; diff --git a/examples/cpp/route_guide/route_guide_server.cc b/examples/cpp/route_guide/route_guide_server.cc index 5867c167128..49239665179 100644 --- a/examples/cpp/route_guide/route_guide_server.cc +++ b/examples/cpp/route_guide/route_guide_server.cc @@ -29,7 +29,11 @@ #include #include #include "helper.h" +#ifdef BAZEL_BUILD +#include "examples/protos/route_guide.grpc.pb.h" +#else #include "route_guide.grpc.pb.h" +#endif using grpc::Server; using grpc::ServerBuilder; @@ -147,24 +151,25 @@ class RouteGuideImpl final : public RouteGuide::Service { Status RouteChat(ServerContext* context, ServerReaderWriter* stream) override { - std::vector received_notes; RouteNote note; while (stream->Read(¬e)) { - for (const RouteNote& n : received_notes) { + std::unique_lock lock(mu_); + for (const RouteNote& n : received_notes_) { if (n.location().latitude() == note.location().latitude() && n.location().longitude() == note.location().longitude()) { stream->Write(n); } } - received_notes.push_back(note); + received_notes_.push_back(note); } return Status::OK; } private: - std::vector feature_list_; + std::mutex mu_; + std::vector received_notes_; }; void RunServer(const std::string& db_path) { diff --git a/examples/python/errors/BUILD.bazel b/examples/python/errors/BUILD.bazel new file mode 100644 index 00000000000..b07dd12ebd3 --- /dev/null +++ b/examples/python/errors/BUILD.bazel @@ -0,0 +1,56 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@grpc_python_dependencies//:requirements.bzl", "requirement") + +py_library( + name = "client", + testonly = 1, + srcs = ["client.py"], + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_status/grpc_status:grpc_status", + "//examples:py_helloworld", + requirement('googleapis-common-protos'), + ], +) + +py_library( + name = "server", + testonly = 1, + srcs = ["server.py"], + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_status/grpc_status:grpc_status", + "//examples:py_helloworld", + ] + select({ + "//conditions:default": [requirement("futures")], + "//:python3": [], + }), +) + +py_test( + name = "test/_error_handling_example_test", + srcs = ["test/_error_handling_example_test.py"], + deps = [ + ":client", + ":server", + "//src/python/grpcio_tests/tests:bazel_namespace_package_hack", + ], + size = "small", + imports = [ + "../../../src/python/grpcio_status", + "../../../src/python/grpcio_tests", + ], +) diff --git a/examples/python/errors/README.md b/examples/python/errors/README.md new file mode 100644 index 00000000000..2cfc26a93b0 --- /dev/null +++ b/examples/python/errors/README.md @@ -0,0 +1,107 @@ +# gRPC Python Error Handling Example + +The goal of this example is sending error status from server that is more complicated than a code and detail string. + +The definition for an RPC method in proto files contains request message and response message. There are many error states that can be shared across RPC methods (e.g. stack trace, insufficient quota). Using a different path to handle error will make the code more maintainable. + +Ideally, the final status of an RPC should be described in the trailing headers of HTTP2, and gRPC Python provides helper functions in `grpcio-status` package to assist the packing and unpacking of error status. + + +### Requirement +``` +grpcio>=1.18.0 +grpcio-status>=1.18.0 +googleapis-common-protos>=1.5.5 +``` + + +### Error Detail Proto + +You may provide any custom proto message as error detail in your implementation. Here are protos are defined by Google Cloud Library Team: + +* [code.proto]([https://github.com/googleapis/api-common-protos/blob/master/google/rpc/code.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/code.proto)) contains definition of RPC error codes. +* [error_details.proto]([https://github.com/googleapis/api-common-protos/blob/master/google/rpc/error_details.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/error_details.proto)) contains definitions of common error details. + + +### Definition of Status Proto + +Here is the definition of Status proto. For full text, please see [status.proto](https://github.com/googleapis/api-common-protos/blob/87185dfffad4afa5a33a8c153f0e1ea53b4f85dc/google/rpc/status.proto). + +```proto +// The `Status` type defines a logical error model that is suitable for different +// programming environments, including REST APIs and RPC APIs. It is used by +// [gRPC](https://github.com/grpc). The error model is designed to be: +// +// - Simple to use and understand for most users +// - Flexible enough to meet unexpected needs +// +// # Overview +// +// The `Status` message contains three pieces of data: error code, error message, +// and error details. The error code should be an enum value of +// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The +// error message should be a developer-facing English message that helps +// developers *understand* and *resolve* the error. If a localized user-facing +// error message is needed, put the localized message in the error details or +// localize it in the client. The optional error details may contain arbitrary +// information about the error. There is a predefined set of error detail types +// in the package `google.rpc` that can be used for common error conditions. +// +// # Language mapping +// +// The `Status` message is the logical representation of the error model, but it +// is not necessarily the actual wire format. When the `Status` message is +// exposed in different client libraries and different wire protocols, it can be +// mapped differently. For example, it will likely be mapped to some exceptions +// in Java, but more likely mapped to some error codes in C. +// +// # Other uses +// +// The error model and the `Status` message can be used in a variety of +// environments, either with or without APIs, to provide a +// consistent developer experience across different environments. +// +// Example uses of this error model include: +// +// - Partial errors. If a service needs to return partial errors to the client, +// it may embed the `Status` in the normal response to indicate the partial +// errors. +// +// - Workflow errors. A typical workflow has multiple steps. Each step may +// have a `Status` message for error reporting. +// +// - Batch operations. If a client uses batch request and batch response, the +// `Status` message should be used directly inside batch response, one for +// each error sub-response. +// +// - Asynchronous operations. If an API call embeds asynchronous operation +// results in its response, the status of those operations should be +// represented directly using the `Status` message. +// +// - Logging. If some API errors are stored in logs, the message `Status` could +// be used directly after any stripping needed for security/privacy reasons. +message Status { + // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. + int32 code = 1; + + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. + string message = 2; + + // A list of messages that carry the error details. There is a common set of + // message types for APIs to use. + repeated google.protobuf.Any details = 3; +} +``` + + +### Usage of Well-Known-Proto `Any` + +Please check [ProtoBuf Document: Any](https://developers.google.com/protocol-buffers/docs/reference/python-generated#any) + +```Python +any_message.Pack(message) +any_message.Unpack(message) +assert any_message.Is(message.DESCRIPTOR) +``` diff --git a/examples/python/errors/client.py b/examples/python/errors/client.py new file mode 100644 index 00000000000..a79b8fce1bd --- /dev/null +++ b/examples/python/errors/client.py @@ -0,0 +1,56 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This example handles rich error status in client-side.""" + +from __future__ import print_function +import logging + +import grpc +from grpc_status import rpc_status +from google.rpc import error_details_pb2 + +from examples.protos import helloworld_pb2 +from examples.protos import helloworld_pb2_grpc + +_LOGGER = logging.getLogger(__name__) + + +def process(stub): + try: + response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice')) + _LOGGER.info('Call success: %s', response.message) + except grpc.RpcError as rpc_error: + _LOGGER.error('Call failure: %s', rpc_error) + status = rpc_status.from_call(rpc_error) + for detail in status.details: + if detail.Is(error_details_pb2.QuotaFailure.DESCRIPTOR): + info = error_details_pb2.QuotaFailure() + detail.Unpack(info) + _LOGGER.error('Quota failure: %s', info) + else: + raise RuntimeError('Unexpected failure: %s' % detail) + + +def main(): + # NOTE(gRPC Python Team): .close() is possible on a channel and should be + # used in circumstances in which the with statement does not fit the needs + # of the code. + with grpc.insecure_channel('localhost:50051') as channel: + stub = helloworld_pb2_grpc.GreeterStub(channel) + process(stub) + + +if __name__ == '__main__': + logging.basicConfig() + main() diff --git a/examples/python/errors/server.py b/examples/python/errors/server.py new file mode 100644 index 00000000000..f49586b848a --- /dev/null +++ b/examples/python/errors/server.py @@ -0,0 +1,90 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""This example sends out rich error status from server-side.""" + +from concurrent import futures +import time +import logging +import threading + +import grpc +from grpc_status import rpc_status + +from google.protobuf import any_pb2 +from google.rpc import code_pb2, status_pb2, error_details_pb2 + +from examples.protos import helloworld_pb2 +from examples.protos import helloworld_pb2_grpc + +_ONE_DAY_IN_SECONDS = 60 * 60 * 24 + + +def create_greet_limit_exceed_error_status(name): + detail = any_pb2.Any() + detail.Pack( + error_details_pb2.QuotaFailure( + violations=[ + error_details_pb2.QuotaFailure.Violation( + subject="name: %s" % name, + description="Limit one greeting per person", + ) + ],)) + return status_pb2.Status( + code=code_pb2.RESOURCE_EXHAUSTED, + message='Request limit exceeded.', + details=[detail], + ) + + +class LimitedGreeter(helloworld_pb2_grpc.GreeterServicer): + + def __init__(self): + self._lock = threading.RLock() + self._greeted = set() + + def SayHello(self, request, context): + with self._lock: + if request.name in self._greeted: + rich_status = create_greet_limit_exceed_error_status( + request.name) + context.abort_with_status(rpc_status.to_status(rich_status)) + else: + self._greeted.add(request.name) + return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name) + + +def create_server(server_address): + server = grpc.server(futures.ThreadPoolExecutor()) + helloworld_pb2_grpc.add_GreeterServicer_to_server(LimitedGreeter(), server) + port = server.add_insecure_port(server_address) + return server, port + + +def serve(server): + server.start() + try: + while True: + time.sleep(_ONE_DAY_IN_SECONDS) + except KeyboardInterrupt: + server.stop(None) + + +def main(): + server, unused_port = create_server('[::]:50051') + serve(server) + + +if __name__ == '__main__': + logging.basicConfig() + main() diff --git a/examples/python/errors/test/_error_handling_example_test.py b/examples/python/errors/test/_error_handling_example_test.py new file mode 100644 index 00000000000..a79ca45e2a1 --- /dev/null +++ b/examples/python/errors/test/_error_handling_example_test.py @@ -0,0 +1,54 @@ +# Copyright 2019 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests of the error handling example.""" + +# NOTE(lidiz) This module only exists in Bazel BUILD file, for more details +# please refer to comments in the "bazel_namespace_package_hack" module. +try: + from tests import bazel_namespace_package_hack + bazel_namespace_package_hack.sys_path_to_site_dir_hack() +except ImportError: + pass + +import unittest +import logging + +import grpc + +from examples.protos import helloworld_pb2_grpc +from examples.python.errors import client as error_handling_client +from examples.python.errors import server as error_handling_server + + +class ErrorHandlingExampleTest(unittest.TestCase): + + def setUp(self): + self._server, port = error_handling_server.create_server('[::]:0') + self._server.start() + self._channel = grpc.insecure_channel('localhost:%d' % port) + + def tearDown(self): + self._channel.close() + self._server.stop(None) + + def test_error_handling_example(self): + stub = helloworld_pb2_grpc.GreeterStub(self._channel) + error_handling_client.process(stub) + error_handling_client.process(stub) + # No unhandled exception raised, test passed! + + +if __name__ == '__main__': + logging.basicConfig() + unittest.main(verbosity=2) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 7afd9ef1a84..b8f3f56a83f 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - # version = '1.20.0-dev' + # version = '1.21.0-dev' version = '0.0.8-dev' s.version = version s.summary = 'gRPC C++ library' @@ -31,7 +31,7 @@ Pod::Spec.new do |s| s.license = 'Apache License, Version 2.0' s.authors = { 'The gRPC contributors' => 'grpc-packages@google.com' } - grpc_version = '1.20.0-dev' + grpc_version = '1.21.0-dev' s.source = { :git => 'https://github.com/grpc/grpc.git', @@ -85,12 +85,16 @@ Pod::Spec.new do |s| 'include/grpcpp/client_context.h', 'include/grpcpp/completion_queue.h', 'include/grpcpp/create_channel.h', + 'include/grpcpp/create_channel_impl.h', 'include/grpcpp/create_channel_posix.h', + 'include/grpcpp/create_channel_posix_impl.h', 'include/grpcpp/ext/health_check_service_server_builder_option.h', 'include/grpcpp/generic/async_generic_service.h', 'include/grpcpp/generic/generic_stub.h', + 'include/grpcpp/generic/generic_stub_impl.h', 'include/grpcpp/grpcpp.h', 'include/grpcpp/health_check_service_interface.h', + 'include/grpcpp/health_check_service_interface_impl.h', 'include/grpcpp/impl/call.h', 'include/grpcpp/impl/channel_argument_option.h', 'include/grpcpp/impl/client_unary_call.h', @@ -101,18 +105,25 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/rpc_service_method.h', 'include/grpcpp/impl/serialization_traits.h', 'include/grpcpp/impl/server_builder_option.h', + 'include/grpcpp/impl/server_builder_option_impl.h', 'include/grpcpp/impl/server_builder_plugin.h', 'include/grpcpp/impl/server_initializer.h', + 'include/grpcpp/impl/server_initializer_impl.h', 'include/grpcpp/impl/service_type.h', 'include/grpcpp/resource_quota.h', + 'include/grpcpp/resource_quota_impl.h', 'include/grpcpp/security/auth_context.h', 'include/grpcpp/security/auth_metadata_processor.h', + 'include/grpcpp/security/auth_metadata_processor_impl.h', 'include/grpcpp/security/credentials.h', 'include/grpcpp/security/server_credentials.h', + 'include/grpcpp/security/server_credentials_impl.h', 'include/grpcpp/server.h', 'include/grpcpp/server_builder.h', + 'include/grpcpp/server_builder_impl.h', 'include/grpcpp/server_context.h', 'include/grpcpp/server_posix.h', + 'include/grpcpp/server_posix_impl.h', 'include/grpcpp/support/async_stream.h', 'include/grpcpp/support/async_unary_call.h', 'include/grpcpp/support/byte_buffer.h', @@ -253,8 +264,10 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/atomic.h', 'src/core/lib/gprpp/fork.h', 'src/core/lib/gprpp/manual_constructor.h', + 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', 'src/core/lib/gprpp/mutex_lock.h', + 'src/core/lib/gprpp/pair.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', @@ -568,8 +581,10 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/atomic.h', 'src/core/lib/gprpp/fork.h', 'src/core/lib/gprpp/manual_constructor.h', + 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', 'src/core/lib/gprpp/mutex_lock.h', + 'src/core/lib/gprpp/pair.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/avl/avl.h', diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 8e544b0641c..bab7ce4378e 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.20.0-dev' + version = '1.21.0-dev' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' @@ -208,8 +208,10 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/atomic.h', 'src/core/lib/gprpp/fork.h', 'src/core/lib/gprpp/manual_constructor.h', + 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', 'src/core/lib/gprpp/mutex_lock.h', + 'src/core/lib/gprpp/pair.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/gpr/alloc.cc', @@ -855,7 +857,15 @@ Pod::Spec.new do |s| 'src/core/ext/filters/http/client_authority_filter.cc', 'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc', 'src/core/ext/filters/workarounds/workaround_utils.cc', - 'src/core/plugin_registry/grpc_plugin_registry.cc' + 'src/core/plugin_registry/grpc_plugin_registry.cc', + 'src/core/lib/iomgr/cfstream_handle.cc', + 'src/core/lib/iomgr/endpoint_cfstream.cc', + 'src/core/lib/iomgr/error_cfstream.cc', + 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', + 'src/core/lib/iomgr/tcp_client_cfstream.cc', + 'src/core/lib/iomgr/cfstream_handle.h', + 'src/core/lib/iomgr/endpoint_cfstream.h', + 'src/core/lib/iomgr/error_cfstream.h' ss.private_header_files = 'src/core/lib/gpr/alloc.h', 'src/core/lib/gpr/arena.h', @@ -877,8 +887,10 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/atomic.h', 'src/core/lib/gprpp/fork.h', 'src/core/lib/gprpp/manual_constructor.h', + 'src/core/lib/gprpp/map.h', 'src/core/lib/gprpp/memory.h', 'src/core/lib/gprpp/mutex_lock.h', + 'src/core/lib/gprpp/pair.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', @@ -1160,26 +1172,15 @@ Pod::Spec.new do |s| 'src/core/ext/filters/message_size/message_size_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h', - 'src/core/ext/filters/workarounds/workaround_utils.h' + 'src/core/ext/filters/workarounds/workaround_utils.h', + 'src/core/lib/iomgr/cfstream_handle.h', + 'src/core/lib/iomgr/endpoint_cfstream.h', + 'src/core/lib/iomgr/error_cfstream.h' end + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream-Implementation' do |ss| - ss.header_mappings_dir = '.' ss.dependency "#{s.name}/Implementation", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } - ss.source_files = 'src/core/lib/iomgr/cfstream_handle.cc', - 'src/core/lib/iomgr/endpoint_cfstream.cc', - 'src/core/lib/iomgr/error_cfstream.cc', - 'src/core/lib/iomgr/iomgr_posix_cfstream.cc', - 'src/core/lib/iomgr/tcp_client_cfstream.cc', - 'src/core/lib/iomgr/cfstream_handle.h', - 'src/core/lib/iomgr/endpoint_cfstream.h', - 'src/core/lib/iomgr/error_cfstream.h' - ss.private_header_files = 'src/core/lib/iomgr/cfstream_handle.h', - 'src/core/lib/iomgr/endpoint_cfstream.h', - 'src/core/lib/iomgr/error_cfstream.h' end s.subspec 'Cronet-Interface' do |ss| diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 3de74e49033..0e905bd97bd 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.20.0-dev' + version = '1.21.0-dev' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' @@ -53,12 +53,10 @@ Pod::Spec.new do |s| ss.source_files = "#{src_dir}/*.{h,m}" end + + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC/CFStream', version ss.dependency "#{s.name}/Main", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.pod_target_xcconfig = { diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 6121f67ae29..df86ef7ed34 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.20.0-dev' + version = '1.21.0-dev' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index c19419f1857..b3c7a55a2e1 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.20.0-dev' + version = '1.21.0-dev' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' @@ -64,14 +64,9 @@ Pod::Spec.new do |s| ss.dependency 'gRPC-Core', version end - # This subspec is mutually exclusive with the `Main` subspec + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC-Core/CFStream-Implementation', version ss.dependency "#{s.name}/Main", version - - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.subspec 'GID' do |ss| diff --git a/grpc.gemspec b/grpc.gemspec index 52db5ecc700..b9d2107ee48 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -30,7 +30,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.7' - s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' + s.add_dependency 'googleapis-common-protos-types', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' @@ -102,8 +102,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/gprpp/atomic.h ) s.files += %w( src/core/lib/gprpp/fork.h ) s.files += %w( src/core/lib/gprpp/manual_constructor.h ) + s.files += %w( src/core/lib/gprpp/map.h ) s.files += %w( src/core/lib/gprpp/memory.h ) s.files += %w( src/core/lib/gprpp/mutex_lock.h ) + s.files += %w( src/core/lib/gprpp/pair.h ) s.files += %w( src/core/lib/gprpp/thd.h ) s.files += %w( src/core/lib/profiling/timers.h ) s.files += %w( src/core/lib/gpr/alloc.cc ) diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index b62bfcbb61a..0349e31bb3b 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -193,6 +193,7 @@ #define GPR_PLATFORM_STRING "ios" #define GPR_CPU_IPHONE 1 #define GPR_PTHREAD_TLS 1 +#define GRPC_CFSTREAM 1 /* the c-ares resolver isnt safe to enable on iOS */ #define GRPC_ARES 0 #else /* TARGET_OS_IPHONE */ @@ -235,7 +236,6 @@ #define GPR_POSIX_SYNC 1 #define GPR_POSIX_TIME 1 #define GPR_GETPID_IN_UNISTD_H 1 -/* TODO(mxyan): Remove when CFStream becomes default */ #ifndef GRPC_CFSTREAM #define GPR_SUPPORT_CHANNELS_FROM_FD 1 #endif diff --git a/include/grpcpp/create_channel.h b/include/grpcpp/create_channel.h index e8a2a70581d..6d444be9803 100644 --- a/include/grpcpp/create_channel.h +++ b/include/grpcpp/create_channel.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,60 +19,36 @@ #ifndef GRPCPP_CREATE_CHANNEL_H #define GRPCPP_CREATE_CHANNEL_H -#include - -#include -#include -#include -#include -#include +#include namespace grpc { -/// Create a new \a Channel pointing to \a target. -/// -/// \param target The URI of the endpoint to connect to. -/// \param creds Credentials to use for the created channel. If it does not -/// hold an object or is invalid, a lame channel (one on which all operations -/// fail) is returned. -std::shared_ptr CreateChannel( +static inline std::shared_ptr CreateChannel( const grpc::string& target, - const std::shared_ptr& creds); + const std::shared_ptr& creds) { + return ::grpc_impl::CreateChannel(target, creds); +} -/// Create a new \em custom \a Channel pointing to \a target. -/// -/// \warning For advanced use and testing ONLY. Override default channel -/// arguments only if necessary. -/// -/// \param target The URI of the endpoint to connect to. -/// \param creds Credentials to use for the created channel. If it does not -/// hold an object or is invalid, a lame channel (one on which all operations -/// fail) is returned. -/// \param args Options for channel creation. -std::shared_ptr CreateCustomChannel( +static inline std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, - const ChannelArguments& args); + const ChannelArguments& args) { + return ::grpc_impl::CreateCustomChannel(target, creds, args); +} namespace experimental { -/// Create a new \em custom \a Channel pointing to \a target with \a -/// interceptors being invoked per call. -/// -/// \warning For advanced use and testing ONLY. Override default channel -/// arguments only if necessary. -/// -/// \param target The URI of the endpoint to connect to. -/// \param creds Credentials to use for the created channel. If it does not -/// hold an object or is invalid, a lame channel (one on which all operations -/// fail) is returned. -/// \param args Options for channel creation. -std::shared_ptr CreateCustomChannelWithInterceptors( + +static inline std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args, std::vector< std::unique_ptr> - interceptor_creators); + interceptor_creators) { + return ::grpc_impl::experimental::CreateCustomChannelWithInterceptors( + target, creds, args, std::move(interceptor_creators)); +} + } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/create_channel_impl.h b/include/grpcpp/create_channel_impl.h new file mode 100644 index 00000000000..214a537a3cb --- /dev/null +++ b/include/grpcpp/create_channel_impl.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_CREATE_CHANNEL_IMPL_H +#define GRPCPP_CREATE_CHANNEL_IMPL_H + +#include + +#include +#include +#include +#include +#include + +namespace grpc_impl { + +/// Create a new \a Channel pointing to \a target. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not +/// hold an object or is invalid, a lame channel (one on which all operations +/// fail) is returned. +std::shared_ptr CreateChannel( + const grpc::string& target, + const std::shared_ptr& creds); + +/// Create a new \em custom \a Channel pointing to \a target. +/// +/// \warning For advanced use and testing ONLY. Override default channel +/// arguments only if necessary. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not +/// hold an object or is invalid, a lame channel (one on which all operations +/// fail) is returned. +/// \param args Options for channel creation. +std::shared_ptr CreateCustomChannel( + const grpc::string& target, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args); + +namespace experimental { +/// Create a new \em custom \a Channel pointing to \a target with \a +/// interceptors being invoked per call. +/// +/// \warning For advanced use and testing ONLY. Override default channel +/// arguments only if necessary. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not +/// hold an object or is invalid, a lame channel (one on which all operations +/// fail) is returned. +/// \param args Options for channel creation. +std::shared_ptr CreateCustomChannelWithInterceptors( + const grpc::string& target, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args, + std::vector< + std::unique_ptr> + interceptor_creators); +} // namespace experimental +} // namespace grpc_impl + +#endif // GRPCPP_CREATE_CHANNEL_IMPL_H diff --git a/include/grpcpp/create_channel_posix.h b/include/grpcpp/create_channel_posix.h index 808514041b8..b8a1f5e5c46 100644 --- a/include/grpcpp/create_channel_posix.h +++ b/include/grpcpp/create_channel_posix.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,46 +19,34 @@ #ifndef GRPCPP_CREATE_CHANNEL_POSIX_H #define GRPCPP_CREATE_CHANNEL_POSIX_H -#include - -#include -#include -#include +#include namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -/// Create a new \a Channel communicating over the given file descriptor. -/// -/// \param target The name of the target. -/// \param fd The file descriptor representing a socket. -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, - int fd); +static inline std::shared_ptr CreateInsecureChannelFromFd( + const grpc::string& target, int fd) { + return ::grpc_impl::CreateInsecureChannelFromFd(target, fd); +} -/// Create a new \a Channel communicating over given file descriptor with custom -/// channel arguments. -/// -/// \param target The name of the target. -/// \param fd The file descriptor representing a socket. -/// \param args Options for channel creation. -std::shared_ptr CreateCustomInsecureChannelFromFd( - const grpc::string& target, int fd, const ChannelArguments& args); +static inline std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const ChannelArguments& args) { + return ::grpc_impl::CreateCustomInsecureChannelFromFd(target, fd, args); +} namespace experimental { -/// Create a new \a Channel communicating over given file descriptor with custom -/// channel arguments. -/// -/// \param target The name of the target. -/// \param fd The file descriptor representing a socket. -/// \param args Options for channel creation. -/// \param interceptor_creators Vector of interceptor factory objects. -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( +static inline std::shared_ptr +CreateCustomInsecureChannelWithInterceptorsFromFd( const grpc::string& target, int fd, const ChannelArguments& args, std::unique_ptr>> - interceptor_creators); + interceptor_creators) { + return ::grpc_impl::experimental:: + CreateCustomInsecureChannelWithInterceptorsFromFd( + target, fd, args, std::move(interceptor_creators)); +} } // namespace experimental diff --git a/include/grpcpp/create_channel_posix_impl.h b/include/grpcpp/create_channel_posix_impl.h new file mode 100644 index 00000000000..5c11120611a --- /dev/null +++ b/include/grpcpp/create_channel_posix_impl.h @@ -0,0 +1,70 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H +#define GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H + +#include + +#include +#include +#include + +namespace grpc_impl { + +#ifdef GPR_SUPPORT_CHANNELS_FROM_FD + +/// Create a new \a Channel communicating over the given file descriptor. +/// +/// \param target The name of the target. +/// \param fd The file descriptor representing a socket. +std::shared_ptr CreateInsecureChannelFromFd( + const grpc::string& target, int fd); + +/// Create a new \a Channel communicating over given file descriptor with custom +/// channel arguments. +/// +/// \param target The name of the target. +/// \param fd The file descriptor representing a socket. +/// \param args Options for channel creation. +std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args); + +namespace experimental { + +/// Create a new \a Channel communicating over given file descriptor with custom +/// channel arguments. +/// +/// \param target The name of the target. +/// \param fd The file descriptor representing a socket. +/// \param args Options for channel creation. +/// \param interceptor_creators Vector of interceptor factory objects. +std::shared_ptr +CreateCustomInsecureChannelWithInterceptorsFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args, + std::unique_ptr>> + interceptor_creators); + +} // namespace experimental + +#endif // GPR_SUPPORT_CHANNELS_FROM_FD + +} // namespace grpc_impl + +#endif // GRPCPP_CREATE_CHANNEL_POSIX_IMPL_H diff --git a/include/grpcpp/ext/channelz_service_plugin.h b/include/grpcpp/ext/channelz_service_plugin.h index af3192d4513..95cb93e3216 100644 --- a/include/grpcpp/ext/channelz_service_plugin.h +++ b/include/grpcpp/ext/channelz_service_plugin.h @@ -19,20 +19,15 @@ #ifndef GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H #define GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_H -#include - -#include -#include -#include +#include namespace grpc { namespace channelz { namespace experimental { -/// Add channelz server plugin to \a ServerBuilder. This function should -/// be called at static initialization time. This service is experimental -/// for now. Track progress in https://github.com/grpc/grpc/issues/15988. -void InitChannelzService(); +static inline void InitChannelzService() { + ::grpc_impl::channelz::experimental::InitChannelzService(); +} } // namespace experimental } // namespace channelz diff --git a/include/grpcpp/ext/channelz_service_plugin_impl.h b/include/grpcpp/ext/channelz_service_plugin_impl.h new file mode 100644 index 00000000000..3a5f3c4b99e --- /dev/null +++ b/include/grpcpp/ext/channelz_service_plugin_impl.h @@ -0,0 +1,41 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H +#define GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H + +#include + +#include +#include +#include + +namespace grpc_impl { +namespace channelz { +namespace experimental { + +/// Add channelz server plugin to \a ServerBuilder. This function should +/// be called at static initialization time. This service is experimental +/// for now. Track progress in https://github.com/grpc/grpc/issues/15988. +void InitChannelzService(); + +} // namespace experimental +} // namespace channelz +} // namespace grpc_impl + +#endif // GRPCPP_EXT_CHANNELZ_SERVICE_PLUGIN_IMPL_H diff --git a/include/grpcpp/ext/proto_server_reflection_plugin.h b/include/grpcpp/ext/proto_server_reflection_plugin.h index 1cfdc1b6ccf..f6f2202ffb3 100644 --- a/include/grpcpp/ext/proto_server_reflection_plugin.h +++ b/include/grpcpp/ext/proto_server_reflection_plugin.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,34 +19,17 @@ #ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H -#include -#include - -namespace grpc { -class ServerInitializer; -class ProtoServerReflection; -} // namespace grpc +#include namespace grpc { namespace reflection { -class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { - public: - ProtoServerReflectionPlugin(); - ::grpc::string name() override; - void InitServer(::grpc::ServerInitializer* si) override; - void Finish(::grpc::ServerInitializer* si) override; - void ChangeArguments(const ::grpc::string& name, void* value) override; - bool has_async_methods() const override; - bool has_sync_methods() const override; - - private: - std::shared_ptr reflection_service_; -}; +typedef ::grpc_impl::reflection::ProtoServerReflectionPlugin + ProtoServerReflectionPlugin; -/// Add proto reflection plugin to \a ServerBuilder. -/// This function should be called at the static initialization time. -void InitProtoReflectionServerBuilderPlugin(); +static inline void InitProtoReflectionServerBuilderPlugin() { + ::grpc_impl::reflection::InitProtoReflectionServerBuilderPlugin(); +} } // namespace reflection } // namespace grpc diff --git a/include/grpcpp/ext/proto_server_reflection_plugin_impl.h b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h new file mode 100644 index 00000000000..a06fe14cdd7 --- /dev/null +++ b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H +#define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H + +#include +#include + +namespace grpc { +class ProtoServerReflection; +} // namespace grpc + +namespace grpc_impl { +class ServerInitializer; + +namespace reflection { + +class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { + public: + ProtoServerReflectionPlugin(); + ::grpc::string name() override; + void InitServer(::grpc_impl::ServerInitializer* si) override; + void Finish(::grpc_impl::ServerInitializer* si) override; + void ChangeArguments(const ::grpc::string& name, void* value) override; + bool has_async_methods() const override; + bool has_sync_methods() const override; + + private: + std::shared_ptr reflection_service_; +}; + +/// Add proto reflection plugin to \a ServerBuilder. +/// This function should be called at the static initialization time. +void InitProtoReflectionServerBuilderPlugin(); + +} // namespace reflection +} // namespace grpc_impl + +#endif // GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H diff --git a/include/grpcpp/ext/server_load_reporting.h b/include/grpcpp/ext/server_load_reporting.h index 939569c19aa..0c39a9e9830 100644 --- a/include/grpcpp/ext/server_load_reporting.h +++ b/include/grpcpp/ext/server_load_reporting.h @@ -19,32 +19,22 @@ #ifndef GRPCPP_EXT_SERVER_LOAD_REPORTING_H #define GRPCPP_EXT_SERVER_LOAD_REPORTING_H -#include - -#include -#include -#include -#include +#include namespace grpc { namespace load_reporter { namespace experimental { -// The ServerBuilderOption to enable server-side load reporting feature. To -// enable the feature, please make sure the binary builds with the -// grpcpp_server_load_reporting library and set this option in the -// ServerBuilder. -class LoadReportingServiceServerBuilderOption : public ServerBuilderOption { - public: - void UpdateArguments(::grpc::ChannelArguments* args) override; - void UpdatePlugins(std::vector>* - plugins) override; -}; +typedef ::grpc_impl::load_reporter::experimental:: + LoadReportingServiceServerBuilderOption + LoadReportingServiceServerBuilderOption; -// Adds the load reporting cost with \a cost_name and \a cost_value in the -// trailing metadata of the server context. -void AddLoadReportingCost(grpc::ServerContext* ctx, - const grpc::string& cost_name, double cost_value); +static inline void AddLoadReportingCost(grpc::ServerContext* ctx, + const grpc::string& cost_name, + double cost_value) { + ::grpc_impl::load_reporter::experimental::AddLoadReportingCost(ctx, cost_name, + cost_value); +} } // namespace experimental } // namespace load_reporter diff --git a/include/grpcpp/ext/server_load_reporting_impl.h b/include/grpcpp/ext/server_load_reporting_impl.h new file mode 100644 index 00000000000..1b27e0af6be --- /dev/null +++ b/include/grpcpp/ext/server_load_reporting_impl.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H +#define GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H + +#include + +#include +#include +#include +#include + +namespace grpc_impl { +namespace load_reporter { +namespace experimental { + +// The ServerBuilderOption to enable server-side load reporting feature. To +// enable the feature, please make sure the binary builds with the +// grpcpp_server_load_reporting library and set this option in the +// ServerBuilder. +class LoadReportingServiceServerBuilderOption + : public grpc::ServerBuilderOption { + public: + void UpdateArguments(::grpc::ChannelArguments* args) override; + void UpdatePlugins(std::vector>* + plugins) override; +}; + +// Adds the load reporting cost with \a cost_name and \a cost_value in the +// trailing metadata of the server context. +void AddLoadReportingCost(grpc::ServerContext* ctx, + const grpc::string& cost_name, double cost_value); + +} // namespace experimental +} // namespace load_reporter +} // namespace grpc_impl + +#endif // GRPCPP_EXT_SERVER_LOAD_REPORTING_IMPL_H diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index 9252599bac3..f4c4664f53c 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -19,85 +19,11 @@ #ifndef GRPCPP_GENERIC_GENERIC_STUB_H #define GRPCPP_GENERIC_GENERIC_STUB_H -#include - -#include -#include -#include -#include -#include +#include namespace grpc { -class CompletionQueue; -typedef ClientAsyncReaderWriter - GenericClientAsyncReaderWriter; -typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; - -/// Generic stubs provide a type-unsafe interface to call gRPC methods -/// by name. -class GenericStub final { - public: - explicit GenericStub(std::shared_ptr channel) - : channel_(channel) {} - - /// Setup a call to a named method \a method using \a context, but don't - /// start it. Let it be started explicitly with StartCall and a tag. - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr PrepareCall( - ClientContext* context, const grpc::string& method, CompletionQueue* cq); - - /// Setup a unary call to a named method \a method using \a context, and don't - /// start it. Let it be started explicitly with StartCall. - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr PrepareUnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer& request, CompletionQueue* cq); - - /// DEPRECATED for multi-threaded use - /// Begin a call to a named method \a method using \a context. - /// A tag \a tag will be delivered to \a cq when the call has been started - /// (i.e, initial metadata has been sent). - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr Call( - ClientContext* context, const grpc::string& method, CompletionQueue* cq, - void* tag); - - /// NOTE: class experimental_type is not part of the public API of this class - /// TODO(vjpai): Move these contents to the public API of GenericStub when - /// they are no longer experimental - class experimental_type { - public: - explicit experimental_type(GenericStub* stub) : stub_(stub) {} - - /// Setup and start a unary call to a named method \a method using - /// \a context and specifying the \a request and \a response buffers. - void UnaryCall(ClientContext* context, const grpc::string& method, - const ByteBuffer* request, ByteBuffer* response, - std::function on_completion); - - /// Setup a call to a named method \a method using \a context and tied to - /// \a reactor . Like any other bidi streaming RPC, it will not be activated - /// until StartCall is invoked on its reactor. - void PrepareBidiStreamingCall( - ClientContext* context, const grpc::string& method, - experimental::ClientBidiReactor* reactor); - - private: - GenericStub* stub_; - }; - - /// NOTE: The function experimental() is not stable public API. It is a view - /// to the experimental components of this class. It may be changed or removed - /// at any time. - experimental_type experimental() { return experimental_type(this); } - - private: - std::shared_ptr channel_; -}; +typedef ::grpc_impl::GenericStub GenericStub; } // namespace grpc diff --git a/include/grpcpp/generic/generic_stub_impl.h b/include/grpcpp/generic/generic_stub_impl.h new file mode 100644 index 00000000000..2d6a11de923 --- /dev/null +++ b/include/grpcpp/generic/generic_stub_impl.h @@ -0,0 +1,108 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_GENERIC_GENERIC_STUB_IMPL_H +#define GRPCPP_GENERIC_GENERIC_STUB_IMPL_H + +#include + +#include +#include +#include +#include +#include + +namespace grpc { + +class CompletionQueue; +typedef ClientAsyncReaderWriter + GenericClientAsyncReaderWriter; +typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; +} // namespace grpc +namespace grpc_impl { + +/// Generic stubs provide a type-unsafe interface to call gRPC methods +/// by name. +class GenericStub final { + public: + explicit GenericStub(std::shared_ptr channel) + : channel_(channel) {} + + /// Setup a call to a named method \a method using \a context, but don't + /// start it. Let it be started explicitly with StartCall and a tag. + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr PrepareCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq); + + /// Setup a unary call to a named method \a method using \a context, and don't + /// start it. Let it be started explicitly with StartCall. + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr PrepareUnaryCall( + grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer& request, grpc::CompletionQueue* cq); + + /// DEPRECATED for multi-threaded use + /// Begin a call to a named method \a method using \a context. + /// A tag \a tag will be delivered to \a cq when the call has been started + /// (i.e, initial metadata has been sent). + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr Call( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq, void* tag); + + /// NOTE: class experimental_type is not part of the public API of this class + /// TODO(vjpai): Move these contents to the public API of GenericStub when + /// they are no longer experimental + class experimental_type { + public: + explicit experimental_type(GenericStub* stub) : stub_(stub) {} + + /// Setup and start a unary call to a named method \a method using + /// \a context and specifying the \a request and \a response buffers. + void UnaryCall(grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer* request, grpc::ByteBuffer* response, + std::function on_completion); + + /// Setup a call to a named method \a method using \a context and tied to + /// \a reactor . Like any other bidi streaming RPC, it will not be activated + /// until StartCall is invoked on its reactor. + void PrepareBidiStreamingCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::experimental::ClientBidiReactor* reactor); + + private: + GenericStub* stub_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + private: + std::shared_ptr channel_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_GENERIC_GENERIC_STUB_IMPL_H diff --git a/include/grpcpp/health_check_service_interface.h b/include/grpcpp/health_check_service_interface.h index dfd4c3983af..a51b0d18bba 100644 --- a/include/grpcpp/health_check_service_interface.h +++ b/include/grpcpp/health_check_service_interface.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,39 +19,22 @@ #ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H #define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_H -#include +#include namespace grpc { const char kHealthCheckServiceInterfaceArg[] = "grpc.health_check_service_interface"; -/// The gRPC server uses this interface to expose the health checking service -/// without depending on protobuf. -class HealthCheckServiceInterface { - public: - virtual ~HealthCheckServiceInterface() {} - - /// Set or change the serving status of the given \a service_name. - virtual void SetServingStatus(const grpc::string& service_name, - bool serving) = 0; - /// Apply to all registered service names. - virtual void SetServingStatus(bool serving) = 0; - - /// Set all registered service names to not serving and prevent future - /// state changes. - virtual void Shutdown() {} -}; - -/// Enable/disable the default health checking service. This applies to all C++ -/// servers created afterwards. For each server, user can override the default -/// with a HealthCheckServiceServerBuilderOption. -/// NOT thread safe. -void EnableDefaultHealthCheckService(bool enable); - -/// Returns whether the default health checking service is enabled. -/// NOT thread safe. -bool DefaultHealthCheckServiceEnabled(); +typedef ::grpc_impl::HealthCheckServiceInterface HealthCheckServiceInterface; + +static inline void EnableDefaultHealthCheckService(bool enable) { + ::grpc_impl::EnableDefaultHealthCheckService(enable); +} + +static inline bool DefaultHealthCheckServiceEnabled() { + return ::grpc_impl::DefaultHealthCheckServiceEnabled(); +} } // namespace grpc diff --git a/include/grpcpp/health_check_service_interface_impl.h b/include/grpcpp/health_check_service_interface_impl.h new file mode 100644 index 00000000000..025dadb4e59 --- /dev/null +++ b/include/grpcpp/health_check_service_interface_impl.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H +#define GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H + +#include + +namespace grpc_impl { + +/// The gRPC server uses this interface to expose the health checking service +/// without depending on protobuf. +class HealthCheckServiceInterface { + public: + virtual ~HealthCheckServiceInterface() {} + + /// Set or change the serving status of the given \a service_name. + virtual void SetServingStatus(const grpc::string& service_name, + bool serving) = 0; + /// Apply to all registered service names. + virtual void SetServingStatus(bool serving) = 0; + + /// Set all registered service names to not serving and prevent future + /// state changes. + virtual void Shutdown() {} +}; + +/// Enable/disable the default health checking service. This applies to all C++ +/// servers created afterwards. For each server, user can override the default +/// with a HealthCheckServiceServerBuilderOption. +/// NOT thread safe. +void EnableDefaultHealthCheckService(bool enable); + +/// Returns whether the default health checking service is enabled. +/// NOT thread safe. +bool DefaultHealthCheckServiceEnabled(); + +} // namespace grpc_impl + +#endif // GRPCPP_HEALTH_CHECK_SERVICE_INTERFACE_IMPL_H diff --git a/include/grpcpp/impl/codegen/completion_queue.h b/include/grpcpp/impl/codegen/completion_queue.h index 4812f0253d4..73556ce9899 100644 --- a/include/grpcpp/impl/codegen/completion_queue.h +++ b/include/grpcpp/impl/codegen/completion_queue.h @@ -41,6 +41,10 @@ struct grpc_completion_queue; +namespace grpc_impl { + +class ServerBuilder; +} namespace grpc { template @@ -63,7 +67,6 @@ class ChannelInterface; class ClientContext; class CompletionQueue; class Server; -class ServerBuilder; class ServerContext; class ServerInterface; @@ -405,7 +408,7 @@ class ServerCompletionQueue : public CompletionQueue { polling_type_(polling_type) {} grpc_cq_polling_type polling_type_; - friend class ServerBuilder; + friend class ::grpc_impl::ServerBuilder; friend class Server; }; diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index 335d5709db6..ce27b156283 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -37,11 +37,43 @@ namespace grpc { // Declare base class of all reactors as internal namespace internal { +// Forward declarations +template +class CallbackClientStreamingHandler; +template +class CallbackServerStreamingHandler; +template +class CallbackBidiHandler; + class ServerReactor { public: virtual ~ServerReactor() = default; virtual void OnDone() = 0; virtual void OnCancel() = 0; + + private: + friend class ::grpc::ServerContext; + template + friend class CallbackClientStreamingHandler; + template + friend class CallbackServerStreamingHandler; + template + friend class CallbackBidiHandler; + + // The ServerReactor is responsible for tracking when it is safe to call + // OnCancel. This function should not be called until after OnStarted is done + // and the RPC has completed with a cancellation. This is tracked by counting + // how many of these conditions have been met and calling OnCancel when none + // remain unmet. + + void MaybeCallOnCancel() { + if (on_cancel_conditions_remaining_.fetch_sub( + 1, std::memory_order_acq_rel) == 1) { + OnCancel(); + } + } + + std::atomic_int on_cancel_conditions_remaining_{2}; }; } // namespace internal @@ -169,9 +201,13 @@ class ServerCallbackReaderWriter { // The following classes are the reactor interfaces that are to be implemented // by the user, returned as the result of the method handler for a callback -// method, and activated by the call to OnStarted. Note that none of the classes -// are pure; all reactions have a default empty reaction so that the user class -// only needs to override those classes that it cares about. +// method, and activated by the call to OnStarted. The library guarantees that +// OnStarted will be called for any reactor that has been created using a +// method handler registered on a service. No operation initiation method may be +// called until after the call to OnStarted. +// Note that none of the classes are pure; all reactions have a default empty +// reaction so that the user class only needs to override those classes that it +// cares about. /// \a ServerBidiReactor is the interface for a bidirectional streaming RPC. template @@ -179,6 +215,9 @@ class ServerBidiReactor : public internal::ServerReactor { public: ~ServerBidiReactor() = default; + /// Do NOT call any operation initiation method (names that start with Start) + /// until after the library has called OnStarted on this object. + /// Send any initial metadata stored in the RPC context. If not invoked, /// any initial metadata will be passed along with the first Write or the /// Finish (if there are no writes). @@ -245,7 +284,10 @@ class ServerBidiReactor : public internal::ServerReactor { /// \param[in] s The status outcome of this RPC void Finish(Status s) { stream_->Finish(std::move(s)); } - /// Notify the application that a streaming RPC has started + /// Notify the application that a streaming RPC has started and that it is now + /// ok to call any operation initiation method. An RPC is considered started + /// after the server has received all initial metadata from the client, which + /// is a result of the client calling StartCall(). /// /// \param[in] context The context object now associated with this RPC virtual void OnStarted(ServerContext* context) {} @@ -580,6 +622,8 @@ class CallbackClientStreamingHandler : public MethodHandler { reader->BindReactor(reactor); reactor->OnStarted(param.server_context, reader->response()); + // The earliest that OnCancel can be called is after OnStarted is done. + reactor->MaybeCallOnCancel(); reader->MaybeDone(); } @@ -722,6 +766,8 @@ class CallbackServerStreamingHandler : public MethodHandler { std::move(param.call_requester), reactor); writer->BindReactor(reactor); reactor->OnStarted(param.server_context, writer->request()); + // The earliest that OnCancel can be called is after OnStarted is done. + reactor->MaybeCallOnCancel(); writer->MaybeDone(); } @@ -898,6 +944,8 @@ class CallbackBidiHandler : public MethodHandler { stream->BindReactor(reactor); reactor->OnStarted(param.server_context); + // The earliest that OnCancel can be called is after OnStarted is done. + reactor->MaybeCallOnCancel(); stream->MaybeDone(); } diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index f599e037fd5..a0b0a580979 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -28,6 +28,10 @@ #include #include +namespace grpc_impl { + +class ServerCredentials; +} namespace grpc { class AsyncGenericService; @@ -35,7 +39,6 @@ class Channel; class GenericServerContext; class ServerCompletionQueue; class ServerContext; -class ServerCredentials; class Service; extern CoreCodegenInterface* g_core_codegen_interface; @@ -150,7 +153,7 @@ class ServerInterface : public internal::CallHook { /// /// \warning It's an error to call this method on an already started server. virtual int AddListeningPort(const grpc::string& addr, - ServerCredentials* creds) = 0; + grpc_impl::ServerCredentials* creds) = 0; /// Start the server. /// diff --git a/include/grpcpp/impl/server_builder_option.h b/include/grpcpp/impl/server_builder_option.h index c7b7801dab3..4b3d6b54118 100644 --- a/include/grpcpp/impl/server_builder_option.h +++ b/include/grpcpp/impl/server_builder_option.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,24 +19,11 @@ #ifndef GRPCPP_IMPL_SERVER_BUILDER_OPTION_H #define GRPCPP_IMPL_SERVER_BUILDER_OPTION_H -#include -#include - -#include -#include +#include namespace grpc { -/// Interface to pass an option to a \a ServerBuilder. -class ServerBuilderOption { - public: - virtual ~ServerBuilderOption() {} - /// Alter the \a ChannelArguments used to create the gRPC server. - virtual void UpdateArguments(ChannelArguments* args) = 0; - /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder. - virtual void UpdatePlugins( - std::vector>* plugins) = 0; -}; +typedef ::grpc_impl::ServerBuilderOption ServerBuilderOption; } // namespace grpc diff --git a/include/grpcpp/impl/server_builder_option_impl.h b/include/grpcpp/impl/server_builder_option_impl.h new file mode 100644 index 00000000000..8271d0f56b2 --- /dev/null +++ b/include/grpcpp/impl/server_builder_option_impl.h @@ -0,0 +1,43 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_SERVER_BUILDER_OPTION_IMPL_H +#define GRPCPP_IMPL_SERVER_BUILDER_OPTION_IMPL_H + +#include +#include + +#include +#include + +namespace grpc_impl { + +/// Interface to pass an option to a \a ServerBuilder. +class ServerBuilderOption { + public: + virtual ~ServerBuilderOption() {} + /// Alter the \a ChannelArguments used to create the gRPC server. + virtual void UpdateArguments(grpc::ChannelArguments* args) = 0; + /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder. + virtual void UpdatePlugins( + std::vector>* plugins) = 0; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_IMPL_SERVER_BUILDER_OPTION_IMPL_H diff --git a/include/grpcpp/impl/server_builder_plugin.h b/include/grpcpp/impl/server_builder_plugin.h index 39450b42d56..dd600a839d7 100644 --- a/include/grpcpp/impl/server_builder_plugin.h +++ b/include/grpcpp/impl/server_builder_plugin.h @@ -23,10 +23,13 @@ #include -namespace grpc { +namespace grpc_impl { class ServerBuilder; class ServerInitializer; +} // namespace grpc_impl +namespace grpc { + class ChannelArguments; /// This interface is meant for internal usage only. Implementations of this @@ -40,14 +43,14 @@ class ServerBuilderPlugin { /// UpdateServerBuilder will be called at an early stage in /// ServerBuilder::BuildAndStart(), right after the ServerBuilderOptions have /// done their updates. - virtual void UpdateServerBuilder(ServerBuilder* builder) {} + virtual void UpdateServerBuilder(grpc_impl::ServerBuilder* builder) {} /// InitServer will be called in ServerBuilder::BuildAndStart(), after the /// Server instance is created. - virtual void InitServer(ServerInitializer* si) = 0; + virtual void InitServer(grpc_impl::ServerInitializer* si) = 0; /// Finish will be called at the end of ServerBuilder::BuildAndStart(). - virtual void Finish(ServerInitializer* si) = 0; + virtual void Finish(grpc_impl::ServerInitializer* si) = 0; /// ChangeArguments is an interface that can be used in /// ServerBuilderOption::UpdatePlugins diff --git a/include/grpcpp/impl/server_initializer.h b/include/grpcpp/impl/server_initializer.h index f949fabfe6f..d40bb98feb6 100644 --- a/include/grpcpp/impl/server_initializer.h +++ b/include/grpcpp/impl/server_initializer.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,36 +19,11 @@ #ifndef GRPCPP_IMPL_SERVER_INITIALIZER_H #define GRPCPP_IMPL_SERVER_INITIALIZER_H -#include -#include - -#include +#include namespace grpc { -class Server; -class Service; - -class ServerInitializer { - public: - ServerInitializer(Server* server) : server_(server) {} - - bool RegisterService(std::shared_ptr service) { - if (!server_->RegisterService(nullptr, service.get())) { - return false; - } - default_services_.push_back(service); - return true; - } - - const std::vector* GetServiceList() { - return &server_->services_; - } - - private: - Server* server_; - std::vector > default_services_; -}; +typedef ::grpc_impl::ServerInitializer ServerInitializer; } // namespace grpc diff --git a/include/grpcpp/impl/server_initializer_impl.h b/include/grpcpp/impl/server_initializer_impl.h new file mode 100644 index 00000000000..ff610efa2ac --- /dev/null +++ b/include/grpcpp/impl/server_initializer_impl.h @@ -0,0 +1,57 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_SERVER_INITIALIZER_IMPL_H +#define GRPCPP_IMPL_SERVER_INITIALIZER_IMPL_H + +#include +#include + +#include + +namespace grpc { + +class Server; +class Service; +} // namespace grpc +namespace grpc_impl { + +class ServerInitializer { + public: + ServerInitializer(grpc::Server* server) : server_(server) {} + + bool RegisterService(std::shared_ptr service) { + if (!server_->RegisterService(nullptr, service.get())) { + return false; + } + default_services_.push_back(service); + return true; + } + + const std::vector* GetServiceList() { + return &server_->services_; + } + + private: + grpc::Server* server_; + std::vector > default_services_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_IMPL_SERVER_INITIALIZER_IMPL_H diff --git a/include/grpcpp/opencensus.h b/include/grpcpp/opencensus.h index 29b221f7674..14c6add1d9e 100644 --- a/include/grpcpp/opencensus.h +++ b/include/grpcpp/opencensus.h @@ -19,29 +19,20 @@ #ifndef GRPCPP_OPENCENSUS_H #define GRPCPP_OPENCENSUS_H -#include "opencensus/trace/span.h" +#include "grpcpp/opencensus_impl.h" namespace grpc { -// These symbols in this file will not be included in the binary unless -// grpc_opencensus_plugin build target was added as a dependency. At the moment -// it is only setup to be built with Bazel. -// Registers the OpenCensus plugin with gRPC, so that it will be used for future -// RPCs. This must be called before any views are created. -void RegisterOpenCensusPlugin(); - -// RPC stats definitions, defined by -// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md - -// Registers the cumulative gRPC views so that they will be exported by any -// registered stats exporter. For on-task stats, construct a View using the -// ViewDescriptors below. -void RegisterOpenCensusViewsForExport(); - -class ServerContext; - -// Returns the tracing Span for the current RPC. -::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context); +static inline void RegisterOpenCensusPlugin() { + ::grpc_impl::RegisterOpenCensusPlugin(); +} +static inline void RegisterOpenCensusViewsForExport() { + ::grpc_impl::RegisterOpenCensusViewsForExport(); +} +static inline ::opencensus::trace::Span GetSpanFromServerContext( + ServerContext* context) { + return ::grpc_impl::GetSpanFromServerContext(context); +} } // namespace grpc diff --git a/include/grpcpp/opencensus_impl.h b/include/grpcpp/opencensus_impl.h new file mode 100644 index 00000000000..631d2b861fd --- /dev/null +++ b/include/grpcpp/opencensus_impl.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_OPENCENSUS_IMPL_H +#define GRPCPP_OPENCENSUS_IMPL_H + +#include "opencensus/trace/span.h" + +namespace grpc { + +class ServerContext; +} +namespace grpc_impl { +// These symbols in this file will not be included in the binary unless +// grpc_opencensus_plugin build target was added as a dependency. At the moment +// it is only setup to be built with Bazel. + +// Registers the OpenCensus plugin with gRPC, so that it will be used for future +// RPCs. This must be called before any views are created. +void RegisterOpenCensusPlugin(); + +// RPC stats definitions, defined by +// https://github.com/census-instrumentation/opencensus-specs/blob/master/stats/gRPC.md + +// Registers the cumulative gRPC views so that they will be exported by any +// registered stats exporter. For on-task stats, construct a View using the +// ViewDescriptors below. +void RegisterOpenCensusViewsForExport(); + +// Returns the tracing Span for the current RPC. +::opencensus::trace::Span GetSpanFromServerContext( + grpc::ServerContext* context); + +} // namespace grpc_impl + +#endif // GRPCPP_OPENCENSUS_IMPL_H diff --git a/include/grpcpp/resource_quota.h b/include/grpcpp/resource_quota.h index 50bd1cb849a..333767b95c5 100644 --- a/include/grpcpp/resource_quota.h +++ b/include/grpcpp/resource_quota.h @@ -1,6 +1,6 @@ /* * - * Copyright 2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,50 +19,11 @@ #ifndef GRPCPP_RESOURCE_QUOTA_H #define GRPCPP_RESOURCE_QUOTA_H -struct grpc_resource_quota; - -#include -#include +#include namespace grpc { -/// ResourceQuota represents a bound on memory and thread usage by the gRPC -/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), -/// or a client channel (via \a ChannelArguments). -/// gRPC will attempt to keep memory and threads used by all attached entities -/// below the ResourceQuota bound. -class ResourceQuota final : private GrpcLibraryCodegen { - public: - /// \param name - a unique name for this ResourceQuota. - explicit ResourceQuota(const grpc::string& name); - ResourceQuota(); - ~ResourceQuota(); - - /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller - /// than the current size of the pool, memory usage will be monotonically - /// decreased until it falls under \a new_size. - /// No time bound is given for this to occur however. - ResourceQuota& Resize(size_t new_size); - - /// Set the max number of threads that can be allocated from this - /// ResourceQuota object. - /// - /// If the new_max_threads value is smaller than the current value, no new - /// threads are allocated until the number of active threads fall below - /// new_max_threads. There is no time bound on when this may happen i.e none - /// of the current threads are forcefully destroyed and all threads run their - /// normal course. - ResourceQuota& SetMaxThreads(int new_max_threads); - - grpc_resource_quota* c_resource_quota() const { return impl_; } - - private: - ResourceQuota(const ResourceQuota& rhs); - ResourceQuota& operator=(const ResourceQuota& rhs); - - grpc_resource_quota* const impl_; -}; - +typedef ::grpc_impl::ResourceQuota ResourceQuota; } // namespace grpc #endif // GRPCPP_RESOURCE_QUOTA_H diff --git a/include/grpcpp/resource_quota_impl.h b/include/grpcpp/resource_quota_impl.h new file mode 100644 index 00000000000..16c0e35385b --- /dev/null +++ b/include/grpcpp/resource_quota_impl.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_RESOURCE_QUOTA_IMPL_H +#define GRPCPP_RESOURCE_QUOTA_IMPL_H + +struct grpc_resource_quota; + +#include +#include + +namespace grpc_impl { + +/// ResourceQuota represents a bound on memory and thread usage by the gRPC +/// library. A ResourceQuota can be attached to a server (via \a ServerBuilder), +/// or a client channel (via \a ChannelArguments). +/// gRPC will attempt to keep memory and threads used by all attached entities +/// below the ResourceQuota bound. +class ResourceQuota final : private ::grpc::GrpcLibraryCodegen { + public: + /// \param name - a unique name for this ResourceQuota. + explicit ResourceQuota(const grpc::string& name); + ResourceQuota(); + ~ResourceQuota(); + + /// Resize this \a ResourceQuota to a new size. If \a new_size is smaller + /// than the current size of the pool, memory usage will be monotonically + /// decreased until it falls under \a new_size. + /// No time bound is given for this to occur however. + ResourceQuota& Resize(size_t new_size); + + /// Set the max number of threads that can be allocated from this + /// ResourceQuota object. + /// + /// If the new_max_threads value is smaller than the current value, no new + /// threads are allocated until the number of active threads fall below + /// new_max_threads. There is no time bound on when this may happen i.e none + /// of the current threads are forcefully destroyed and all threads run their + /// normal course. + ResourceQuota& SetMaxThreads(int new_max_threads); + + grpc_resource_quota* c_resource_quota() const { return impl_; } + + private: + ResourceQuota(const ResourceQuota& rhs); + ResourceQuota& operator=(const ResourceQuota& rhs); + + grpc_resource_quota* const impl_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_RESOURCE_QUOTA_IMPL_H diff --git a/include/grpcpp/security/auth_metadata_processor.h b/include/grpcpp/security/auth_metadata_processor.h index 30e24c9f0bc..1b66b72b967 100644 --- a/include/grpcpp/security/auth_metadata_processor.h +++ b/include/grpcpp/security/auth_metadata_processor.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,42 +19,11 @@ #ifndef GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H #define GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_H -#include - -#include -#include -#include +#include namespace grpc { -/// Interface allowing custom server-side authorization based on credentials -/// encoded in metadata. Objects of this type can be passed to -/// \a ServerCredentials::SetAuthMetadataProcessor(). -class AuthMetadataProcessor { - public: - typedef std::multimap InputMetadata; - typedef std::multimap OutputMetadata; - - virtual ~AuthMetadataProcessor() {} - - /// If this method returns true, the \a Process function will be scheduled in - /// a different thread from the one processing the call. - virtual bool IsBlocking() const { return true; } - - /// context is read/write: it contains the properties of the channel peer and - /// it is the job of the Process method to augment it with properties derived - /// from the passed-in auth_metadata. - /// consumed_auth_metadata needs to be filled with metadata that has been - /// consumed by the processor and will be removed from the call. - /// response_metadata is the metadata that will be sent as part of the - /// response. - /// If the return value is not Status::OK, the rpc call will be aborted with - /// the error code and error message sent back to the client. - virtual Status Process(const InputMetadata& auth_metadata, - AuthContext* context, - OutputMetadata* consumed_auth_metadata, - OutputMetadata* response_metadata) = 0; -}; +typedef ::grpc_impl::AuthMetadataProcessor AuthMetadataProcessor; } // namespace grpc diff --git a/include/grpcpp/security/auth_metadata_processor_impl.h b/include/grpcpp/security/auth_metadata_processor_impl.h new file mode 100644 index 00000000000..ae454200622 --- /dev/null +++ b/include/grpcpp/security/auth_metadata_processor_impl.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_IMPL_H +#define GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_IMPL_H + +#include + +#include +#include +#include + +namespace grpc_impl { + +/// Interface allowing custom server-side authorization based on credentials +/// encoded in metadata. Objects of this type can be passed to +/// \a ServerCredentials::SetAuthMetadataProcessor(). +class AuthMetadataProcessor { + public: + typedef std::multimap InputMetadata; + typedef std::multimap OutputMetadata; + + virtual ~AuthMetadataProcessor() {} + + /// If this method returns true, the \a Process function will be scheduled in + /// a different thread from the one processing the call. + virtual bool IsBlocking() const { return true; } + + /// context is read/write: it contains the properties of the channel peer and + /// it is the job of the Process method to augment it with properties derived + /// from the passed-in auth_metadata. + /// consumed_auth_metadata needs to be filled with metadata that has been + /// consumed by the processor and will be removed from the call. + /// response_metadata is the metadata that will be sent as part of the + /// response. + /// If the return value is not Status::OK, the rpc call will be aborted with + /// the error code and error message sent back to the client. + virtual grpc::Status Process(const InputMetadata& auth_metadata, + grpc::AuthContext* context, + OutputMetadata* consumed_auth_metadata, + OutputMetadata* response_metadata) = 0; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_SECURITY_AUTH_METADATA_PROCESSOR_IMPL_H diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h index dfea3900048..34d2e2ea463 100644 --- a/include/grpcpp/security/credentials.h +++ b/include/grpcpp/security/credentials.h @@ -33,23 +33,31 @@ struct grpc_call; namespace grpc { -class ChannelArguments; -class Channel; -class SecureChannelCredentials; -class CallCredentials; -class SecureCallCredentials; +class CallCredentials; +class ChannelArguments; class ChannelCredentials; +} // namespace grpc +namespace grpc_impl { +std::shared_ptr CreateCustomChannel( + const grpc::string& target, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args); namespace experimental { -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators); } // namespace experimental +} // namespace grpc_impl +namespace grpc { +class Channel; +class SecureChannelCredentials; +class SecureCallCredentials; /// A channel credentials object encapsulates all the state needed by a client /// to authenticate with a server for a given channel. @@ -70,18 +78,18 @@ class ChannelCredentials : private GrpcLibraryCodegen { virtual SecureChannelCredentials* AsSecureCredentials() = 0; private: - friend std::shared_ptr CreateCustomChannel( + friend std::shared_ptr grpc_impl::CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, - const ChannelArguments& args); + const grpc::ChannelArguments& args); friend std::shared_ptr - experimental::CreateCustomChannelWithInterceptors( + grpc_impl::experimental::CreateCustomChannelWithInterceptors( const grpc::string& target, const std::shared_ptr& creds, - const ChannelArguments& args, - std::vector< - std::unique_ptr> + const grpc::ChannelArguments& args, + std::vector> interceptor_creators); virtual std::shared_ptr CreateChannel( diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index bd00a0a1737..7e643ae7400 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,39 +19,11 @@ #ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_H #define GRPCPP_SECURITY_SERVER_CREDENTIALS_H -#include -#include - -#include -#include -#include - -struct grpc_server; +#include namespace grpc { -class Server; - -/// Wrapper around \a grpc_server_credentials, a way to authenticate a server. -class ServerCredentials { - public: - virtual ~ServerCredentials(); - - /// This method is not thread-safe and has to be called before the server is - /// started. The last call to this function wins. - virtual void SetAuthMetadataProcessor( - const std::shared_ptr& processor) = 0; - private: - friend class ::grpc::Server; - - /// Tries to bind \a server to the given \a addr (eg, localhost:1234, - /// 192.168.1.1:31416, [::1]:27182, etc.) - /// - /// \return bound port number on sucess, 0 on failure. - // TODO(dgq): the "port" part seems to be a misnomer. - virtual int AddPortToServer(const grpc::string& addr, - grpc_server* server) = 0; -}; +typedef ::grpc_impl::ServerCredentials ServerCredentials; /// Options to create ServerCredentials with SSL struct SslServerCredentialsOptions { @@ -79,27 +51,29 @@ struct SslServerCredentialsOptions { grpc_ssl_client_certificate_request_type client_certificate_request; }; -/// Builds SSL ServerCredentials given SSL specific options -std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options); +static inline std::shared_ptr SslServerCredentials( + const SslServerCredentialsOptions& options) { + return ::grpc_impl::SslServerCredentials(options); +} -/// Builds insecure server credentials. -std::shared_ptr InsecureServerCredentials(); +static inline std::shared_ptr InsecureServerCredentials() { + return ::grpc_impl::InsecureServerCredentials(); +} namespace experimental { -/// Options to create ServerCredentials with ALTS -struct AltsServerCredentialsOptions { - /// Add fields if needed. -}; +typedef ::grpc_impl::experimental::AltsServerCredentialsOptions + AltsServerCredentialsOptions; -/// Builds ALTS ServerCredentials given ALTS specific options -std::shared_ptr AltsServerCredentials( - const AltsServerCredentialsOptions& options); +static inline std::shared_ptr AltsServerCredentials( + const AltsServerCredentialsOptions& options) { + return ::grpc_impl::experimental::AltsServerCredentials(options); +} -/// Builds Local ServerCredentials. -std::shared_ptr LocalServerCredentials( - grpc_local_connect_type type); +static inline std::shared_ptr LocalServerCredentials( + grpc_local_connect_type type) { + return ::grpc_impl::experimental::LocalServerCredentials(type); +} } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h new file mode 100644 index 00000000000..afe8d22650b --- /dev/null +++ b/include/grpcpp/security/server_credentials_impl.h @@ -0,0 +1,85 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H +#define GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H + +#include +#include + +#include +#include +#include + +struct grpc_server; + +namespace grpc { + +class Server; +struct SslServerCredentialsOptions; +} // namespace grpc +namespace grpc_impl { + +/// Wrapper around \a grpc_server_credentials, a way to authenticate a server. +class ServerCredentials { + public: + virtual ~ServerCredentials(); + + /// This method is not thread-safe and has to be called before the server is + /// started. The last call to this function wins. + virtual void SetAuthMetadataProcessor( + const std::shared_ptr& processor) = 0; + + private: + friend class ::grpc::Server; + + /// Tries to bind \a server to the given \a addr (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.) + /// + /// \return bound port number on success, 0 on failure. + // TODO(dgq): the "port" part seems to be a misnomer. + virtual int AddPortToServer(const grpc::string& addr, + grpc_server* server) = 0; +}; + +/// Builds SSL ServerCredentials given SSL specific options +std::shared_ptr SslServerCredentials( + const grpc::SslServerCredentialsOptions& options); + +/// Builds insecure server credentials. +std::shared_ptr InsecureServerCredentials(); + +namespace experimental { + +/// Options to create ServerCredentials with ALTS +struct AltsServerCredentialsOptions { + /// Add fields if needed. +}; + +/// Builds ALTS ServerCredentials given ALTS specific options +std::shared_ptr AltsServerCredentials( + const AltsServerCredentialsOptions& options); + +/// Builds Local ServerCredentials. +std::shared_ptr LocalServerCredentials( + grpc_local_connect_type type); + +} // namespace experimental +} // namespace grpc_impl + +#endif // GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index f5c99f22df2..2ae9d712012 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -40,12 +41,14 @@ struct grpc_server; +namespace grpc_impl { + +class ServerInitializer; +} namespace grpc { class AsyncGenericService; -class HealthCheckServiceInterface; class ServerContext; -class ServerInitializer; /// Represents a gRPC server. /// @@ -198,8 +201,8 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { } friend class AsyncGenericService; - friend class ServerBuilder; - friend class ServerInitializer; + friend class grpc_impl::ServerBuilder; + friend class grpc_impl::ServerInitializer; class SyncRequest; class CallbackRequestBase; @@ -257,7 +260,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { CompletionQueue* CallbackCQ() override; - ServerInitializer* initializer(); + grpc_impl::ServerInitializer* initializer(); // A vector of interceptor factory objects. // This should be destroyed after health_check_service_ and this requirement @@ -321,7 +324,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // Pointer to the wrapped grpc_server. grpc_server* server_; - std::unique_ptr server_initializer_; + std::unique_ptr server_initializer_; std::unique_ptr health_check_service_; bool health_check_service_disabled_; diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 18cfbb26c75..33689561825 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015-2016 gRPC authors. + * Copyright 2019 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,323 +19,17 @@ #ifndef GRPCPP_SERVER_BUILDER_H #define GRPCPP_SERVER_BUILDER_H -#include -#include -#include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include +namespace grpc_impl { -struct grpc_resource_quota; - -namespace grpc { - -class AsyncGenericService; -class ResourceQuota; -class CompletionQueue; -class Server; -class ServerCompletionQueue; class ServerCredentials; -class Service; - -namespace testing { -class ServerBuilderPluginTest; -} // namespace testing - -namespace experimental { -class CallbackGenericService; -} // namespace experimental - -/// A builder class for the creation and startup of \a grpc::Server instances. -class ServerBuilder { - public: - ServerBuilder(); - virtual ~ServerBuilder(); - - ////////////////////////////////////////////////////////////////////////////// - // Primary API's - - /// Return a running server which is ready for processing calls. - /// Before calling, one typically needs to ensure that: - /// 1. a service is registered - so that the server knows what to serve - /// (via RegisterService, or RegisterAsyncGenericService) - /// 2. a listening port has been added - so the server knows where to receive - /// traffic (via AddListeningPort) - /// 3. [for async api only] completion queues have been added via - /// AddCompletionQueue - virtual std::unique_ptr BuildAndStart(); - - /// Register a service. This call does not take ownership of the service. - /// The service must exist for the lifetime of the \a Server instance returned - /// by \a BuildAndStart(). - /// Matches requests with any :authority - ServerBuilder& RegisterService(Service* service); - - /// Enlists an endpoint \a addr (port with an optional IP address) to - /// bind the \a grpc::Server object to be created to. - /// - /// It can be invoked multiple times. - /// - /// \param addr_uri The address to try to bind to the server in URI form. If - /// the scheme name is omitted, "dns:///" is assumed. To bind to any address, - /// please use IPv6 any, i.e., [::]:, which also accepts IPv4 - /// connections. Valid values include dns:///localhost:1234, / - /// 192.168.1.1:31416, dns:///[::1]:27182, etc.). - /// \param creds The credentials associated with the server. - /// \param selected_port[out] If not `nullptr`, gets populated with the port - /// number bound to the \a grpc::Server for the corresponding endpoint after - /// it is successfully bound by BuildAndStart(), 0 otherwise. AddListeningPort - /// does not modify this pointer. - ServerBuilder& AddListeningPort(const grpc::string& addr_uri, - std::shared_ptr creds, - int* selected_port = nullptr); - - /// Add a completion queue for handling asynchronous services. - /// - /// Best performance is typically obtained by using one thread per polling - /// completion queue. - /// - /// Caller is required to shutdown the server prior to shutting down the - /// returned completion queue. Caller is also required to drain the - /// completion queue after shutting it down. A typical usage scenario: - /// - /// // While building the server: - /// ServerBuilder builder; - /// ... - /// cq_ = builder.AddCompletionQueue(); - /// server_ = builder.BuildAndStart(); - /// - /// // While shutting down the server; - /// server_->Shutdown(); - /// cq_->Shutdown(); // Always *after* the associated server's Shutdown()! - /// // Drain the cq_ that was created - /// void* ignored_tag; - /// bool ignored_ok; - /// while (cq_->Next(&ignored_tag, &ignored_ok)) { } - /// - /// \param is_frequently_polled This is an optional parameter to inform gRPC - /// library about whether this completion queue would be frequently polled - /// (i.e. by calling \a Next() or \a AsyncNext()). The default value is - /// 'true' and is the recommended setting. Setting this to 'false' (i.e. - /// not polling the completion queue frequently) will have a significantly - /// negative performance impact and hence should not be used in production - /// use cases. - std::unique_ptr AddCompletionQueue( - bool is_frequently_polled = true); - - ////////////////////////////////////////////////////////////////////////////// - // Less commonly used RegisterService variants - - /// Register a service. This call does not take ownership of the service. - /// The service must exist for the lifetime of the \a Server instance returned - /// by \a BuildAndStart(). - /// Only matches requests with :authority \a host - ServerBuilder& RegisterService(const grpc::string& host, Service* service); - - /// Register a generic service. - /// Matches requests with any :authority - /// This is mostly useful for writing generic gRPC Proxies where the exact - /// serialization format is unknown - ServerBuilder& RegisterAsyncGenericService(AsyncGenericService* service); - - ////////////////////////////////////////////////////////////////////////////// - // Fine control knobs - - /// Set max receive message size in bytes. - /// The default is GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH. - ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) { - max_receive_message_size_ = max_receive_message_size; - return *this; - } - - /// Set max send message size in bytes. - /// The default is GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH. - ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) { - max_send_message_size_ = max_send_message_size; - return *this; - } - - /// \deprecated For backward compatibility. - ServerBuilder& SetMaxMessageSize(int max_message_size) { - return SetMaxReceiveMessageSize(max_message_size); - } - - /// Set the support status for compression algorithms. All algorithms are - /// enabled by default. - /// - /// Incoming calls compressed with an unsupported algorithm will fail with - /// \a GRPC_STATUS_UNIMPLEMENTED. - ServerBuilder& SetCompressionAlgorithmSupportStatus( - grpc_compression_algorithm algorithm, bool enabled); - - /// The default compression level to use for all channel calls in the - /// absence of a call-specific level. - ServerBuilder& SetDefaultCompressionLevel(grpc_compression_level level); - - /// The default compression algorithm to use for all channel calls in the - /// absence of a call-specific level. Note that it overrides any compression - /// level set by \a SetDefaultCompressionLevel. - ServerBuilder& SetDefaultCompressionAlgorithm( - grpc_compression_algorithm algorithm); - - /// Set the attached buffer pool for this server - ServerBuilder& SetResourceQuota(const ResourceQuota& resource_quota); - - ServerBuilder& SetOption(std::unique_ptr option); - - /// Options for synchronous servers. - enum SyncServerOption { - NUM_CQS, ///< Number of completion queues. - MIN_POLLERS, ///< Minimum number of polling threads. - MAX_POLLERS, ///< Maximum number of polling threads. - CQ_TIMEOUT_MSEC ///< Completion queue timeout in milliseconds. - }; - - /// Only useful if this is a Synchronous server. - ServerBuilder& SetSyncServerOption(SyncServerOption option, int value); - - /// Add a channel argument (an escape hatch to tuning core library parameters - /// directly) - template - ServerBuilder& AddChannelArgument(const grpc::string& arg, const T& value) { - return SetOption(MakeChannelArgumentOption(arg, value)); - } - - /// For internal use only: Register a ServerBuilderPlugin factory function. - static void InternalAddPluginFactory( - std::unique_ptr (*CreatePlugin)()); - - /// Enable a server workaround. Do not use unless you know what the workaround - /// does. For explanation and detailed descriptions of workarounds, see - /// doc/workarounds.md. - ServerBuilder& EnableWorkaround(grpc_workaround_list id); - - /// NOTE: class experimental_type is not part of the public API of this class. - /// TODO(yashykt): Integrate into public API when this is no longer - /// experimental. - class experimental_type { - public: - explicit experimental_type(ServerBuilder* builder) : builder_(builder) {} - - void SetInterceptorCreators( - std::vector< - std::unique_ptr> - interceptor_creators) { - builder_->interceptor_creators_ = std::move(interceptor_creators); - } - - /// Register a generic service that uses the callback API. - /// Matches requests with any :authority - /// This is mostly useful for writing generic gRPC Proxies where the exact - /// serialization format is unknown - ServerBuilder& RegisterCallbackGenericService( - experimental::CallbackGenericService* service); - - private: - ServerBuilder* builder_; - }; - - /// NOTE: The function experimental() is not stable public API. It is a view - /// to the experimental components of this class. It may be changed or removed - /// at any time. - experimental_type experimental() { return experimental_type(this); } - - protected: - /// Experimental, to be deprecated - struct Port { - grpc::string addr; - std::shared_ptr creds; - int* selected_port; - }; - - /// Experimental, to be deprecated - typedef std::unique_ptr HostString; - struct NamedService { - explicit NamedService(Service* s) : service(s) {} - NamedService(const grpc::string& h, Service* s) - : host(new grpc::string(h)), service(s) {} - HostString host; - Service* service; - }; - - /// Experimental, to be deprecated - std::vector ports() { return ports_; } - - /// Experimental, to be deprecated - std::vector services() { - std::vector service_refs; - for (auto& ptr : services_) { - service_refs.push_back(ptr.get()); - } - return service_refs; - } - - /// Experimental, to be deprecated - std::vector options() { - std::vector option_refs; - for (auto& ptr : options_) { - option_refs.push_back(ptr.get()); - } - return option_refs; - } - - private: - friend class ::grpc::testing::ServerBuilderPluginTest; - - struct SyncServerSettings { - SyncServerSettings() - : num_cqs(1), 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; - - /// Minimum number of threads per completion queue that should be listening - /// to incoming RPCs. - int min_pollers; - - /// Maximum number of threads per completion queue that can be listening to - /// incoming RPCs. - int max_pollers; - - /// The timeout for server completion queue's AsyncNext call. - int cq_timeout_msec; - }; - - int max_receive_message_size_; - int max_send_message_size_; - std::vector> options_; - std::vector> services_; - std::vector ports_; - - SyncServerSettings sync_server_settings_; +class ResourceQuota; +} // namespace grpc_impl - /// List of completion queues added via \a AddCompletionQueue method. - std::vector cqs_; +namespace grpc { - std::shared_ptr creds_; - std::vector> plugins_; - grpc_resource_quota* resource_quota_; - AsyncGenericService* generic_service_{nullptr}; - experimental::CallbackGenericService* callback_generic_service_{nullptr}; - struct { - bool is_set; - grpc_compression_level level; - } maybe_default_compression_level_; - struct { - bool is_set; - grpc_compression_algorithm algorithm; - } maybe_default_compression_algorithm_; - uint32_t enabled_compression_algorithms_bitset_; - std::vector> - interceptor_creators_; -}; +typedef ::grpc_impl::ServerBuilder ServerBuilder; } // namespace grpc diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h new file mode 100644 index 00000000000..25b8091a7df --- /dev/null +++ b/include/grpcpp/server_builder_impl.h @@ -0,0 +1,354 @@ +/* + * + * Copyright 2015-2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SERVER_BUILDER_IMPL_H +#define GRPCPP_SERVER_BUILDER_IMPL_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct grpc_resource_quota; + +namespace grpc_impl { + +class ResourceQuota; +class ServerCredentials; +} // namespace grpc_impl +namespace grpc { + +class AsyncGenericService; +class CompletionQueue; +class Server; +class ServerCompletionQueue; +class Service; + +namespace testing { +class ServerBuilderPluginTest; +} // namespace testing + +namespace experimental { +class CallbackGenericService; +} +} // namespace grpc +namespace grpc_impl { + +/// A builder class for the creation and startup of \a grpc::Server instances. +class ServerBuilder { + public: + ServerBuilder(); + virtual ~ServerBuilder(); + + ////////////////////////////////////////////////////////////////////////////// + // Primary API's + + /// Return a running server which is ready for processing calls. + /// Before calling, one typically needs to ensure that: + /// 1. a service is registered - so that the server knows what to serve + /// (via RegisterService, or RegisterAsyncGenericService) + /// 2. a listening port has been added - so the server knows where to receive + /// traffic (via AddListeningPort) + /// 3. [for async api only] completion queues have been added via + /// AddCompletionQueue + virtual std::unique_ptr BuildAndStart(); + + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the \a Server instance returned + /// by \a BuildAndStart(). + /// Matches requests with any :authority + ServerBuilder& RegisterService(grpc::Service* service); + + /// Enlists an endpoint \a addr (port with an optional IP address) to + /// bind the \a grpc::Server object to be created to. + /// + /// It can be invoked multiple times. + /// + /// \param addr_uri The address to try to bind to the server in URI form. If + /// the scheme name is omitted, "dns:///" is assumed. To bind to any address, + /// please use IPv6 any, i.e., [::]:, which also accepts IPv4 + /// connections. Valid values include dns:///localhost:1234, / + /// 192.168.1.1:31416, dns:///[::1]:27182, etc.). + /// \param creds The credentials associated with the server. + /// \param selected_port[out] If not `nullptr`, gets populated with the port + /// number bound to the \a grpc::Server for the corresponding endpoint after + /// it is successfully bound by BuildAndStart(), 0 otherwise. AddListeningPort + /// does not modify this pointer. + ServerBuilder& AddListeningPort( + const grpc::string& addr_uri, + std::shared_ptr creds, + int* selected_port = nullptr); + + /// Add a completion queue for handling asynchronous services. + /// + /// Best performance is typically obtained by using one thread per polling + /// completion queue. + /// + /// Caller is required to shutdown the server prior to shutting down the + /// returned completion queue. Caller is also required to drain the + /// completion queue after shutting it down. A typical usage scenario: + /// + /// // While building the server: + /// ServerBuilder builder; + /// ... + /// cq_ = builder.AddCompletionQueue(); + /// server_ = builder.BuildAndStart(); + /// + /// // While shutting down the server; + /// server_->Shutdown(); + /// cq_->Shutdown(); // Always *after* the associated server's Shutdown()! + /// // Drain the cq_ that was created + /// void* ignored_tag; + /// bool ignored_ok; + /// while (cq_->Next(&ignored_tag, &ignored_ok)) { } + /// + /// \param is_frequently_polled This is an optional parameter to inform gRPC + /// library about whether this completion queue would be frequently polled + /// (i.e. by calling \a Next() or \a AsyncNext()). The default value is + /// 'true' and is the recommended setting. Setting this to 'false' (i.e. + /// not polling the completion queue frequently) will have a significantly + /// negative performance impact and hence should not be used in production + /// use cases. + std::unique_ptr AddCompletionQueue( + bool is_frequently_polled = true); + + ////////////////////////////////////////////////////////////////////////////// + // Less commonly used RegisterService variants + + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the \a Server instance + /// returned by \a BuildAndStart(). Only matches requests with :authority \a + /// host + ServerBuilder& RegisterService(const grpc::string& host, + grpc::Service* service); + + /// Register a generic service. + /// Matches requests with any :authority + /// This is mostly useful for writing generic gRPC Proxies where the exact + /// serialization format is unknown + ServerBuilder& RegisterAsyncGenericService( + grpc::AsyncGenericService* service); + + ////////////////////////////////////////////////////////////////////////////// + // Fine control knobs + + /// Set max receive message size in bytes. + /// The default is GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH. + ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) { + max_receive_message_size_ = max_receive_message_size; + return *this; + } + + /// Set max send message size in bytes. + /// The default is GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH. + ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) { + max_send_message_size_ = max_send_message_size; + return *this; + } + + /// \deprecated For backward compatibility. + ServerBuilder& SetMaxMessageSize(int max_message_size) { + return SetMaxReceiveMessageSize(max_message_size); + } + + /// Set the support status for compression algorithms. All algorithms are + /// enabled by default. + /// + /// Incoming calls compressed with an unsupported algorithm will fail with + /// \a GRPC_STATUS_UNIMPLEMENTED. + ServerBuilder& SetCompressionAlgorithmSupportStatus( + grpc_compression_algorithm algorithm, bool enabled); + + /// The default compression level to use for all channel calls in the + /// absence of a call-specific level. + ServerBuilder& SetDefaultCompressionLevel(grpc_compression_level level); + + /// The default compression algorithm to use for all channel calls in the + /// absence of a call-specific level. Note that it overrides any compression + /// level set by \a SetDefaultCompressionLevel. + ServerBuilder& SetDefaultCompressionAlgorithm( + grpc_compression_algorithm algorithm); + + /// Set the attached buffer pool for this server + ServerBuilder& SetResourceQuota( + const grpc_impl::ResourceQuota& resource_quota); + + ServerBuilder& SetOption(std::unique_ptr option); + + /// Options for synchronous servers. + enum SyncServerOption { + NUM_CQS, ///< Number of completion queues. + MIN_POLLERS, ///< Minimum number of polling threads. + MAX_POLLERS, ///< Maximum number of polling threads. + CQ_TIMEOUT_MSEC ///< Completion queue timeout in milliseconds. + }; + + /// Only useful if this is a Synchronous server. + ServerBuilder& SetSyncServerOption(SyncServerOption option, int value); + + /// Add a channel argument (an escape hatch to tuning core library parameters + /// directly) + template + ServerBuilder& AddChannelArgument(const grpc::string& arg, const T& value) { + return SetOption(grpc::MakeChannelArgumentOption(arg, value)); + } + + /// For internal use only: Register a ServerBuilderPlugin factory function. + static void InternalAddPluginFactory( + std::unique_ptr (*CreatePlugin)()); + + /// Enable a server workaround. Do not use unless you know what the workaround + /// does. For explanation and detailed descriptions of workarounds, see + /// doc/workarounds.md. + ServerBuilder& EnableWorkaround(grpc_workaround_list id); + + /// NOTE: class experimental_type is not part of the public API of this class. + /// TODO(yashykt): Integrate into public API when this is no longer + /// experimental. + class experimental_type { + public: + explicit experimental_type(grpc_impl::ServerBuilder* builder) + : builder_(builder) {} + + void SetInterceptorCreators( + std::vector> + interceptor_creators) { + builder_->interceptor_creators_ = std::move(interceptor_creators); + } + + /// Register a generic service that uses the callback API. + /// Matches requests with any :authority + /// This is mostly useful for writing generic gRPC Proxies where the exact + /// serialization format is unknown + ServerBuilder& RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service); + + private: + ServerBuilder* builder_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + protected: + /// Experimental, to be deprecated + struct Port { + grpc::string addr; + std::shared_ptr creds; + int* selected_port; + }; + + /// Experimental, to be deprecated + typedef std::unique_ptr HostString; + struct NamedService { + explicit NamedService(grpc::Service* s) : service(s) {} + NamedService(const grpc::string& h, grpc::Service* s) + : host(new grpc::string(h)), service(s) {} + HostString host; + grpc::Service* service; + }; + + /// Experimental, to be deprecated + std::vector ports() { return ports_; } + + /// Experimental, to be deprecated + std::vector services() { + std::vector service_refs; + for (auto& ptr : services_) { + service_refs.push_back(ptr.get()); + } + return service_refs; + } + + /// Experimental, to be deprecated + std::vector options() { + std::vector option_refs; + for (auto& ptr : options_) { + option_refs.push_back(ptr.get()); + } + return option_refs; + } + + private: + friend class ::grpc::testing::ServerBuilderPluginTest; + + struct SyncServerSettings { + SyncServerSettings() + : num_cqs(1), 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; + + /// Minimum number of threads per completion queue that should be listening + /// to incoming RPCs. + int min_pollers; + + /// Maximum number of threads per completion queue that can be listening to + /// incoming RPCs. + int max_pollers; + + /// The timeout for server completion queue's AsyncNext call. + int cq_timeout_msec; + }; + + int max_receive_message_size_; + int max_send_message_size_; + std::vector> options_; + std::vector> services_; + std::vector ports_; + + SyncServerSettings sync_server_settings_; + + /// List of completion queues added via \a AddCompletionQueue method. + std::vector cqs_; + + std::shared_ptr creds_; + std::vector> plugins_; + grpc_resource_quota* resource_quota_; + grpc::AsyncGenericService* generic_service_{nullptr}; + grpc::experimental::CallbackGenericService* callback_generic_service_{ + nullptr}; + struct { + bool is_set; + grpc_compression_level level; + } maybe_default_compression_level_; + struct { + bool is_set; + grpc_compression_algorithm algorithm; + } maybe_default_compression_algorithm_; + uint32_t enabled_compression_algorithms_bitset_; + std::vector< + std::unique_ptr> + interceptor_creators_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_SERVER_BUILDER_IMPL_H diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h new file mode 100644 index 00000000000..771a3a10be9 --- /dev/null +++ b/include/grpcpp/server_impl.h @@ -0,0 +1,360 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SERVER_IMPL_H +#define GRPCPP_SERVER_IMPL_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct grpc_server; + +namespace grpc { + +class AsyncGenericService; +class ServerContext; + +} // namespace grpc + +namespace grpc_impl { + +class HealthCheckServiceInterface; +class ServerInitializer; + +/// Represents a gRPC server. +/// +/// Use a \a grpc::ServerBuilder to create, configure, and start +/// \a Server instances. +class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { + public: + ~Server(); + + /// Block until the server shuts down. + /// + /// \warning The server must be either shutting down or some other thread must + /// call \a Shutdown for this function to ever return. + void Wait() override; + + /// Global callbacks are a set of hooks that are called when server + /// events occur. \a SetGlobalCallbacks method is used to register + /// the hooks with gRPC. Note that + /// the \a GlobalCallbacks instance will be shared among all + /// \a Server instances in an application and can be set exactly + /// once per application. + class GlobalCallbacks { + public: + virtual ~GlobalCallbacks() {} + /// Called before server is created. + virtual void UpdateArguments(grpc::ChannelArguments* args) {} + /// Called before application callback for each synchronous server request + virtual void PreSynchronousRequest(grpc::ServerContext* context) = 0; + /// Called after application callback for each synchronous server request + virtual void PostSynchronousRequest(grpc::ServerContext* context) = 0; + /// Called before server is started. + virtual void PreServerStart(Server* server) {} + /// Called after a server port is added. + virtual void AddPort(Server* server, const grpc::string& addr, + grpc::ServerCredentials* creds, int port) {} + }; + /// Set the global callback object. Can only be called once per application. + /// Does not take ownership of callbacks, and expects the pointed to object + /// to be alive until all server objects in the process have been destroyed. + /// The same \a GlobalCallbacks object will be used throughout the + /// application and is shared among all \a Server objects. + static void SetGlobalCallbacks(GlobalCallbacks* callbacks); + + /// Returns a \em raw pointer to the underlying \a grpc_server instance. + /// EXPERIMENTAL: for internal/test use only + grpc_server* c_server(); + + /// Returns the health check service. + grpc_impl::HealthCheckServiceInterface* GetHealthCheckService() const { + return health_check_service_.get(); + } + + /// Establish a channel for in-process communication + std::shared_ptr InProcessChannel( + const grpc::ChannelArguments& args); + + /// NOTE: class experimental_type is not part of the public API of this class. + /// TODO(yashykt): Integrate into public API when this is no longer + /// experimental. + class experimental_type { + public: + explicit experimental_type(Server* server) : server_(server) {} + + /// Establish a channel for in-process communication with client + /// interceptors + std::shared_ptr InProcessChannelWithInterceptors( + const grpc::ChannelArguments& args, + std::vector> + interceptor_creators); + + private: + Server* server_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + protected: + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the Server instance. + bool RegisterService(const grpc::string* host, + grpc::Service* service) override; + + /// Try binding the server to the given \a addr endpoint + /// (port, and optionally including IP address to bind to). + /// + /// It can be invoked multiple times. Should be used before + /// starting the server. + /// + /// \param addr The address to try to bind to the server (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.). + /// \param creds The credentials associated with the server. + /// + /// \return bound port number on success, 0 on failure. + /// + /// \warning It is an error to call this method on an already started server. + int AddListeningPort(const grpc::string& addr, + grpc::ServerCredentials* creds) override; + + /// NOTE: This is *NOT* a public API. The server constructors are supposed to + /// be used by \a ServerBuilder class only. The constructor will be made + /// 'private' very soon. + /// + /// Server constructors. To be used by \a ServerBuilder only. + /// + /// \param max_message_size Maximum message length that the channel can + /// receive. + /// + /// \param args The channel args + /// + /// \param sync_server_cqs The completion queues to use if the server is a + /// synchronous server (or a hybrid server). The server polls for new RPCs on + /// these queues + /// + /// \param min_pollers The minimum number of polling threads per server + /// completion queue (in param sync_server_cqs) to use for listening to + /// incoming requests (used only in case of sync server) + /// + /// \param max_pollers The maximum number of polling threads per server + /// completion queue (in param sync_server_cqs) to use for listening to + /// incoming requests (used only in case of sync server) + /// + /// \param sync_cq_timeout_msec The timeout to use when calling AsyncNext() on + /// server completion queues passed via sync_server_cqs param. + Server( + int max_message_size, grpc::ChannelArguments* args, + std::shared_ptr>> + sync_server_cqs, + int min_pollers, int max_pollers, int sync_cq_timeout_msec, + grpc_resource_quota* server_rq = nullptr, + std::vector> + interceptor_creators = std::vector>()); + + /// Start the server. + /// + /// \param cqs Completion queues for handling asynchronous services. The + /// caller is required to keep all completion queues live until the server is + /// destroyed. + /// \param num_cqs How many completion queues does \a cqs hold. + void Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) override; + + grpc_server* server() override { return server_; } + + private: + std::vector< + std::unique_ptr>* + interceptor_creators() override { + return &interceptor_creators_; + } + + friend class grpc::AsyncGenericService; + friend class grpc_impl::ServerBuilder; + friend class grpc_impl::ServerInitializer; + + class SyncRequest; + class CallbackRequestBase; + template + class CallbackRequest; + class UnimplementedAsyncRequest; + class UnimplementedAsyncResponse; + + /// SyncRequestThreadManager is an implementation of ThreadManager. This class + /// is responsible for polling for incoming RPCs and calling the RPC handlers. + /// This is only used in case of a Sync server (i.e a server exposing a sync + /// interface) + class SyncRequestThreadManager; + + /// Register a generic service. This call does not take ownership of the + /// service. The service must exist for the lifetime of the Server instance. + void RegisterAsyncGenericService(grpc::AsyncGenericService* service) override; + + /// NOTE: class experimental_registration_type is not part of the public API + /// of this class + /// TODO(vjpai): Move these contents to the public API of Server when + /// they are no longer experimental + class experimental_registration_type final + : public experimental_registration_interface { + public: + explicit experimental_registration_type(Server* server) : server_(server) {} + void RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service) override { + server_->RegisterCallbackGenericService(service); + } + + private: + Server* server_; + }; + + /// TODO(vjpai): Mark this override when experimental type above is deleted + void RegisterCallbackGenericService( + grpc::experimental::CallbackGenericService* service); + + /// NOTE: The function experimental_registration() is not stable public API. + /// It is a view to the experimental components of this class. It may be + /// changed or removed at any time. + experimental_registration_interface* experimental_registration() override { + return &experimental_registration_; + } + + void PerformOpsOnCall(grpc::internal::CallOpSetInterface* ops, + grpc::internal::Call* call) override; + + void ShutdownInternal(gpr_timespec deadline) override; + + int max_receive_message_size() const override { + return max_receive_message_size_; + } + + grpc::CompletionQueue* CallbackCQ() override; + + grpc_impl::ServerInitializer* initializer(); + + // A vector of interceptor factory objects. + // This should be destroyed after health_check_service_ and this requirement + // is satisfied by declaring interceptor_creators_ before + // health_check_service_. (C++ mandates that member objects be destroyed in + // the reverse order of initialization.) + std::vector< + std::unique_ptr> + interceptor_creators_; + + const int max_receive_message_size_; + + /// The following completion queues are ONLY used in case of Sync API + /// i.e. if the server has any services with sync methods. The server uses + /// these completion queues to poll for new RPCs + std::shared_ptr>> + sync_server_cqs_; + + /// List of \a ThreadManager instances (one for each cq in + /// the \a sync_server_cqs) + std::vector> sync_req_mgrs_; + + // Outstanding unmatched callback requests, indexed by method. + // NOTE: Using a gpr_atm rather than atomic_int because atomic_int isn't + // copyable or movable and thus will cause compilation errors. We + // actually only want to extend the vector before the threaded use + // starts, but this is still a limitation. + std::vector callback_unmatched_reqs_count_; + + // List of callback requests to start when server actually starts. + std::list callback_reqs_to_start_; + + // For registering experimental callback generic service; remove when that + // method longer experimental + experimental_registration_type experimental_registration_{this}; + + // Server status + std::mutex mu_; + bool started_; + bool shutdown_; + bool shutdown_notified_; // Was notify called on the shutdown_cv_ + + std::condition_variable shutdown_cv_; + + // It is ok (but not required) to nest callback_reqs_mu_ under mu_ . + // Incrementing callback_reqs_outstanding_ is ok without a lock but it must be + // decremented under the lock in case it is the last request and enables the + // server shutdown. The increment is performance-critical since it happens + // during periods of increasing load; the decrement happens only when memory + // is maxed out, during server shutdown, or (possibly in a future version) + // during decreasing load, so it is less performance-critical. + std::mutex callback_reqs_mu_; + std::condition_variable callback_reqs_done_cv_; + std::atomic_int callback_reqs_outstanding_{0}; + + std::shared_ptr global_callbacks_; + + std::vector services_; + bool has_async_generic_service_{false}; + bool has_callback_generic_service_{false}; + + // Pointer to the wrapped grpc_server. + grpc_server* server_; + + std::unique_ptr server_initializer_; + + std::unique_ptr health_check_service_; + bool health_check_service_disabled_; + + // When appropriate, use a default callback generic service to handle + // unimplemented methods + std::unique_ptr + unimplemented_service_; + + // A special handler for resource exhausted in sync case + std::unique_ptr resource_exhausted_handler_; + + // Handler for callback generic service, if any + std::unique_ptr generic_handler_; + + // callback_cq_ references the callbackable completion queue associated + // with this server (if any). It is set on the first call to CallbackCQ(). + // It is _not owned_ by the server; ownership belongs with its internal + // shutdown callback tag (invoked when the CQ is fully shutdown). + // It is protected by mu_ + grpc::CompletionQueue* callback_cq_ = nullptr; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_SERVER_IMPL_H diff --git a/include/grpcpp/server_posix.h b/include/grpcpp/server_posix.h index ef3ee01a5c6..3d209cbc14f 100644 --- a/include/grpcpp/server_posix.h +++ b/include/grpcpp/server_posix.h @@ -19,21 +19,15 @@ #ifndef GRPCPP_SERVER_POSIX_H #define GRPCPP_SERVER_POSIX_H -#include - -#include -#include +#include namespace grpc { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -/// Add a new client to a \a Server communicating over the given -/// file descriptor. -/// -/// \param server The server to add the client to. -/// \param fd The file descriptor representing a socket. -void AddInsecureChannelFromFd(Server* server, int fd); +static inline void AddInsecureChannelFromFd(Server* server, int fd) { + ::grpc_impl::AddInsecureChannelFromFd(server, fd); +} #endif // GPR_SUPPORT_CHANNELS_FROM_FD diff --git a/include/grpcpp/server_posix_impl.h b/include/grpcpp/server_posix_impl.h new file mode 100644 index 00000000000..c29af271fe9 --- /dev/null +++ b/include/grpcpp/server_posix_impl.h @@ -0,0 +1,42 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SERVER_POSIX_IMPL_H +#define GRPCPP_SERVER_POSIX_IMPL_H + +#include + +#include +#include + +namespace grpc_impl { + +#ifdef GPR_SUPPORT_CHANNELS_FROM_FD + +/// Add a new client to a \a Server communicating over the given +/// file descriptor. +/// +/// \param server The server to add the client to. +/// \param fd The file descriptor representing a socket. +void AddInsecureChannelFromFd(grpc::Server* server, int fd); + +#endif // GPR_SUPPORT_CHANNELS_FROM_FD + +} // namespace grpc + +#endif // GRPCPP_SERVER_POSIX_IMPL_H diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h index 217929d4aca..48ae4246462 100644 --- a/include/grpcpp/support/channel_arguments.h +++ b/include/grpcpp/support/channel_arguments.h @@ -26,13 +26,16 @@ #include #include +namespace grpc_impl { + +class ResourceQuota; +} + namespace grpc { namespace testing { class ChannelArgumentsTest; } // namespace testing -class ResourceQuota; - /// Options for channel creation. The user can use generic setters to pass /// key value pairs down to C channel creation code. For gRPC related options, /// concrete setters are provided. @@ -83,7 +86,7 @@ class ChannelArguments { void SetUserAgentPrefix(const grpc::string& user_agent_prefix); /// Set the buffer pool to be attached to the constructed channel. - void SetResourceQuota(const ResourceQuota& resource_quota); + void SetResourceQuota(const ::grpc_impl::ResourceQuota& resource_quota); /// Set the max receive and send message sizes. void SetMaxReceiveMessageSize(int size); diff --git a/include/grpcpp/support/error_details.h b/include/grpcpp/support/error_details.h index 84931d98f18..07bc750db5c 100644 --- a/include/grpcpp/support/error_details.h +++ b/include/grpcpp/support/error_details.h @@ -19,7 +19,7 @@ #ifndef GRPCPP_SUPPORT_ERROR_DETAILS_H #define GRPCPP_SUPPORT_ERROR_DETAILS_H -#include +#include namespace google { namespace rpc { @@ -29,17 +29,15 @@ class Status; namespace grpc { -/// Map a \a grpc::Status to a \a google::rpc::Status. -/// The given \a to object will be cleared. -/// On success, returns status with OK. -/// Returns status with \a INVALID_ARGUMENT, if failed to deserialize. -/// Returns status with \a FAILED_PRECONDITION, if \a to is nullptr. -Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to); - -/// Map \a google::rpc::Status to a \a grpc::Status. -/// Returns OK on success. -/// Returns status with \a FAILED_PRECONDITION if \a to is nullptr. -Status SetErrorDetails(const ::google::rpc::Status& from, Status* to); +static inline Status ExtractErrorDetails(const Status& from, + ::google::rpc::Status* to) { + return ::grpc_impl::ExtractErrorDetails(from, to); +} + +static inline Status SetErrorDetails(const ::google::rpc::Status& from, + Status* to) { + return ::grpc_impl::SetErrorDetails(from, to); +} } // namespace grpc diff --git a/include/grpcpp/support/error_details_impl.h b/include/grpcpp/support/error_details_impl.h new file mode 100644 index 00000000000..ae5f04ced8f --- /dev/null +++ b/include/grpcpp/support/error_details_impl.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SUPPORT_ERROR_DETAILS_IMPL_H +#define GRPCPP_SUPPORT_ERROR_DETAILS_IMPL_H + +#include + +namespace google { +namespace rpc { +class Status; +} // namespace rpc +} // namespace google + +namespace grpc_impl { + +/// Map a \a grpc::Status to a \a google::rpc::Status. +/// The given \a to object will be cleared. +/// On success, returns status with OK. +/// Returns status with \a INVALID_ARGUMENT, if failed to deserialize. +/// Returns status with \a FAILED_PRECONDITION, if \a to is nullptr. +grpc::Status ExtractErrorDetails(const grpc::Status& from, + ::google::rpc::Status* to); + +/// Map \a google::rpc::Status to a \a grpc::Status. +/// Returns OK on success. +/// Returns status with \a FAILED_PRECONDITION if \a to is nullptr. +grpc::Status SetErrorDetails(const ::google::rpc::Status& from, + grpc::Status* to); + +} // namespace grpc_impl + +#endif // GRPCPP_SUPPORT_ERROR_DETAILS_IMPL_H diff --git a/package.xml b/package.xml index ccdd70bdca3..f3bbb449ac5 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2018-01-19 - 1.20.0dev - 1.20.0dev + 1.21.0dev + 1.21.0dev beta @@ -107,8 +107,10 @@ + + diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index ac0af336f93..778e5c39284 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -382,6 +382,10 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor* service) { "/// Base class for server-side implementations of " "$servicename$\n", "servicename", GetServiceClassName(service)); + out->Print( + "[grpc::BindServiceMethod(typeof($classname$), " + "\"BindService\")]\n", + "classname", GetServiceClassName(service)); out->Print("public abstract partial class $name$\n", "name", GetServerClassName(service)); out->Print("{\n"); diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc index e806f46d814..960fd808dd8 100644 --- a/src/compiler/objective_c_generator.cc +++ b/src/compiler/objective_c_generator.cc @@ -70,6 +70,10 @@ static void PrintAllComments(const DescriptorType* desc, Printer* printer) { } printer->Print("\n"); } + printer->Print(" *\n"); + printer->Print( + " * This method belongs to a set of APIs that have been deprecated. Using" + " the v2 API is recommended.\n"); printer->Print(" */\n"); } @@ -278,6 +282,13 @@ void PrintMethodImplementations(Printer* printer, map< ::grpc::string, ::grpc::string> vars = { {"service_class", ServiceClassName(service)}}; + printer.Print(vars, + "/**\n" + " * The methods in this protocol belong to a set of old APIs " + "that have been deprecated. They do not\n" + " * recognize call options provided in the initializer. Using " + "the v2 protocol is recommended.\n" + " */\n"); printer.Print(vars, "@protocol $service_class$ \n\n"); for (int i = 0; i < service->method_count(); i++) { PrintMethodDeclarations(&printer, service->method(i)); @@ -329,10 +340,13 @@ void PrintMethodImplementations(Printer* printer, "callOptions:(GRPCCallOptions " "*_Nullable)callOptions" " NS_DESIGNATED_INITIALIZER;\n"); - printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); printer.Print( "+ (instancetype)serviceWithHost:(NSString *)host " "callOptions:(GRPCCallOptions *_Nullable)callOptions;\n"); + printer.Print( + "// The following methods belong to a set of old APIs that have been " + "deprecated.\n"); + printer.Print("- (instancetype)initWithHost:(NSString *)host;\n"); printer.Print("+ (instancetype)serviceWithHost:(NSString *)host;\n"); printer.Print("@end\n"); diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 82ce253c83c..86938a51d9b 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -51,6 +51,7 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -91,7 +92,55 @@ grpc_core::TraceFlag grpc_client_channel_routing_trace( * CHANNEL-WIDE FUNCTIONS */ -struct external_connectivity_watcher; +// Forward declaration. +typedef struct client_channel_channel_data channel_data; + +namespace grpc_core { +namespace { + +class ExternalConnectivityWatcher { + public: + class WatcherList { + public: + WatcherList() { gpr_mu_init(&mu_); } + ~WatcherList() { gpr_mu_destroy(&mu_); } + + int size() const; + ExternalConnectivityWatcher* Lookup(grpc_closure* on_complete) const; + void Add(ExternalConnectivityWatcher* watcher); + void Remove(const ExternalConnectivityWatcher* watcher); + + private: + // head_ is guarded by a mutex, since the size() method needs to + // iterate over the list, and it's called from the C-core API + // function grpc_channel_num_external_connectivity_watchers(), which + // is synchronous and therefore cannot run in the combiner. + mutable gpr_mu mu_; + ExternalConnectivityWatcher* head_ = nullptr; + }; + + ExternalConnectivityWatcher(channel_data* chand, grpc_polling_entity pollent, + grpc_connectivity_state* state, + grpc_closure* on_complete, + grpc_closure* watcher_timer_init); + + ~ExternalConnectivityWatcher(); + + private: + static void OnWatchCompleteLocked(void* arg, grpc_error* error); + static void WatchConnectivityStateLocked(void* arg, grpc_error* ignored); + + channel_data* chand_; + grpc_polling_entity pollent_; + grpc_connectivity_state* state_; + grpc_closure* on_complete_; + grpc_closure* watcher_timer_init_; + grpc_closure my_closure_; + ExternalConnectivityWatcher* next_ = nullptr; +}; + +} // namespace +} // namespace grpc_core struct QueuedPick { LoadBalancingPolicy::PickArgs pick; @@ -99,51 +148,53 @@ struct QueuedPick { QueuedPick* next = nullptr; }; -typedef struct client_channel_channel_data { +struct client_channel_channel_data { + // + // Fields set at construction and never modified. + // bool deadline_checking_enabled; bool enable_retries; size_t per_rpc_retry_buffer_size; - - /** combiner protecting all variables below in this data structure */ - grpc_combiner* combiner; - /** owning stack */ grpc_channel_stack* owning_stack; - /** interested parties (owned) */ - grpc_pollset_set* interested_parties; - // Client channel factory. grpc_core::ClientChannelFactory* client_channel_factory; - // Subchannel pool. - grpc_core::RefCountedPtr subchannel_pool; grpc_core::channelz::ClientChannelNode* channelz_node; - // Resolving LB policy. - grpc_core::OrphanablePtr resolving_lb_policy; - // Subchannel picker from LB policy. + // + // Fields used in the data plane. Protected by data_plane_combiner. + // + grpc_combiner* data_plane_combiner; grpc_core::UniquePtr picker; - // Linked list of queued picks. - QueuedPick* queued_picks; - - bool have_service_config; - /** retry throttle data from service config */ + QueuedPick* queued_picks; // Linked list of queued picks. + // Data from service config. + bool received_service_config_data; grpc_core::RefCountedPtr retry_throttle_data; - /** per-method service config data */ grpc_core::RefCountedPtr method_params_table; - /* the following properties are guarded by a mutex since APIs require them - to be instantaneously available */ + // + // Fields used in the control plane. Protected by combiner. + // + grpc_combiner* combiner; + grpc_pollset_set* interested_parties; + grpc_core::RefCountedPtr subchannel_pool; + grpc_core::OrphanablePtr resolving_lb_policy; + grpc_connectivity_state_tracker state_tracker; + + // + // Fields accessed from both data plane and control plane combiners. + // + grpc_core::Atomic disconnect_error; + + // The following properties are guarded by a mutex since APIs require them + // to be instantaneously available. gpr_mu info_mu; grpc_core::UniquePtr info_lb_policy_name; grpc_core::UniquePtr info_service_config_json; - grpc_connectivity_state_tracker state_tracker; - grpc_error* disconnect_error; - - /* external_connectivity_watcher_list head is guarded by its own mutex, since - * counts need to be grabbed immediately without polling on a cq */ - gpr_mu external_connectivity_watcher_list_mu; - struct external_connectivity_watcher* external_connectivity_watcher_list_head; -} channel_data; + grpc_core::ManualConstructor< + grpc_core::ExternalConnectivityWatcher::WatcherList> + external_connectivity_watcher_list; +}; // Forward declarations. static void start_pick_locked(void* arg, grpc_error* ignored); @@ -166,30 +217,215 @@ static const char* get_channel_connectivity_state_change_string( GPR_UNREACHABLE_CODE(return "UNKNOWN"); } -static void set_connectivity_state_and_picker_locked( - channel_data* chand, grpc_connectivity_state state, grpc_error* state_error, - const char* reason, - grpc_core::UniquePtr picker) { - // Update connectivity state. - grpc_connectivity_state_set(&chand->state_tracker, state, state_error, - reason); - if (chand->channelz_node != nullptr) { - chand->channelz_node->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string( - get_channel_connectivity_state_change_string(state))); +namespace grpc_core { +namespace { + +// A fire-and-forget class that sets the channel's connectivity state +// and then hops into the data plane combiner to update the picker. +// Must be instantiated while holding the control plane combiner. +// Deletes itself when done. +class ConnectivityStateAndPickerSetter { + public: + ConnectivityStateAndPickerSetter( + channel_data* chand, grpc_connectivity_state state, + grpc_error* state_error, const char* reason, + UniquePtr picker) + : chand_(chand), picker_(std::move(picker)) { + // Update connectivity state here, while holding control plane combiner. + grpc_connectivity_state_set(&chand->state_tracker, state, state_error, + reason); + if (chand->channelz_node != nullptr) { + chand->channelz_node->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + get_channel_connectivity_state_change_string(state))); + } + // Bounce into the data plane combiner to reset the picker. + GRPC_CHANNEL_STACK_REF(chand->owning_stack, + "ConnectivityStateAndPickerSetter"); + GRPC_CLOSURE_INIT(&closure_, SetPicker, this, + grpc_combiner_scheduler(chand->data_plane_combiner)); + GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); + } + + private: + static void SetPicker(void* arg, grpc_error* ignored) { + auto* self = static_cast(arg); + // Update picker. + self->chand_->picker = std::move(self->picker_); + // Re-process queued picks. + for (QueuedPick* pick = self->chand_->queued_picks; pick != nullptr; + pick = pick->next) { + start_pick_locked(pick->elem, GRPC_ERROR_NONE); + } + // Clean up. + GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack, + "ConnectivityStateAndPickerSetter"); + Delete(self); + } + + channel_data* chand_; + UniquePtr picker_; + grpc_closure closure_; +}; + +// A fire-and-forget class that sets the channel's service config data +// in the data plane combiner. Deletes itself when done. +class ServiceConfigSetter { + public: + ServiceConfigSetter( + channel_data* chand, + RefCountedPtr retry_throttle_data, + RefCountedPtr method_params_table) + : chand_(chand), + retry_throttle_data_(std::move(retry_throttle_data)), + method_params_table_(std::move(method_params_table)) { + GRPC_CHANNEL_STACK_REF(chand->owning_stack, "ServiceConfigSetter"); + GRPC_CLOSURE_INIT(&closure_, SetServiceConfigData, this, + grpc_combiner_scheduler(chand->data_plane_combiner)); + GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); } - // Update picker. - chand->picker = std::move(picker); - // Re-process queued picks. - for (QueuedPick* pick = chand->queued_picks; pick != nullptr; - pick = pick->next) { - start_pick_locked(pick->elem, GRPC_ERROR_NONE); + + private: + static void SetServiceConfigData(void* arg, grpc_error* ignored) { + ServiceConfigSetter* self = static_cast(arg); + channel_data* chand = self->chand_; + // Update channel state. + chand->received_service_config_data = true; + chand->retry_throttle_data = std::move(self->retry_throttle_data_); + chand->method_params_table = std::move(self->method_params_table_); + // Apply service config to queued picks. + for (QueuedPick* pick = chand->queued_picks; pick != nullptr; + pick = pick->next) { + maybe_apply_service_config_to_call_locked(pick->elem); + } + // Clean up. + GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack, "ServiceConfigSetter"); + Delete(self); } + + channel_data* chand_; + RefCountedPtr retry_throttle_data_; + RefCountedPtr method_params_table_; + grpc_closure closure_; +}; + +// +// ExternalConnectivityWatcher::WatcherList +// + +int ExternalConnectivityWatcher::WatcherList::size() const { + MutexLock lock(&mu_); + int count = 0; + for (ExternalConnectivityWatcher* w = head_; w != nullptr; w = w->next_) { + ++count; + } + return count; } -namespace grpc_core { -namespace { +ExternalConnectivityWatcher* ExternalConnectivityWatcher::WatcherList::Lookup( + grpc_closure* on_complete) const { + MutexLock lock(&mu_); + ExternalConnectivityWatcher* w = head_; + while (w != nullptr && w->on_complete_ != on_complete) { + w = w->next_; + } + return w; +} + +void ExternalConnectivityWatcher::WatcherList::Add( + ExternalConnectivityWatcher* watcher) { + GPR_ASSERT(Lookup(watcher->on_complete_) == nullptr); + MutexLock lock(&mu_); + GPR_ASSERT(watcher->next_ == nullptr); + watcher->next_ = head_; + head_ = watcher; +} + +void ExternalConnectivityWatcher::WatcherList::Remove( + const ExternalConnectivityWatcher* watcher) { + MutexLock lock(&mu_); + if (watcher == head_) { + head_ = watcher->next_; + return; + } + for (ExternalConnectivityWatcher* w = head_; w != nullptr; w = w->next_) { + if (w->next_ == watcher) { + w->next_ = w->next_->next_; + return; + } + } + GPR_UNREACHABLE_CODE(return ); +} + +// +// ExternalConnectivityWatcher +// + +ExternalConnectivityWatcher::ExternalConnectivityWatcher( + channel_data* chand, grpc_polling_entity pollent, + grpc_connectivity_state* state, grpc_closure* on_complete, + grpc_closure* watcher_timer_init) + : chand_(chand), + pollent_(pollent), + state_(state), + on_complete_(on_complete), + watcher_timer_init_(watcher_timer_init) { + grpc_polling_entity_add_to_pollset_set(&pollent_, chand_->interested_parties); + GRPC_CHANNEL_STACK_REF(chand_->owning_stack, "ExternalConnectivityWatcher"); + GRPC_CLOSURE_SCHED( + GRPC_CLOSURE_INIT(&my_closure_, WatchConnectivityStateLocked, this, + grpc_combiner_scheduler(chand_->combiner)), + GRPC_ERROR_NONE); +} + +ExternalConnectivityWatcher::~ExternalConnectivityWatcher() { + grpc_polling_entity_del_from_pollset_set(&pollent_, + chand_->interested_parties); + GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack, "ExternalConnectivityWatcher"); +} + +void ExternalConnectivityWatcher::OnWatchCompleteLocked(void* arg, + grpc_error* error) { + ExternalConnectivityWatcher* self = + static_cast(arg); + grpc_closure* on_complete = self->on_complete_; + self->chand_->external_connectivity_watcher_list->Remove(self); + Delete(self); + GRPC_CLOSURE_SCHED(on_complete, GRPC_ERROR_REF(error)); +} + +void ExternalConnectivityWatcher::WatchConnectivityStateLocked( + void* arg, grpc_error* ignored) { + ExternalConnectivityWatcher* self = + static_cast(arg); + if (self->state_ == nullptr) { + // Handle cancellation. + GPR_ASSERT(self->watcher_timer_init_ == nullptr); + ExternalConnectivityWatcher* found = + self->chand_->external_connectivity_watcher_list->Lookup( + self->on_complete_); + if (found != nullptr) { + grpc_connectivity_state_notify_on_state_change( + &found->chand_->state_tracker, nullptr, &found->my_closure_); + } + Delete(self); + return; + } + // New watcher. + self->chand_->external_connectivity_watcher_list->Add(self); + // This assumes that the closure is scheduled on the ExecCtx scheduler + // and that GRPC_CLOSURE_RUN would run the closure immediately. + GRPC_CLOSURE_RUN(self->watcher_timer_init_, GRPC_ERROR_NONE); + GRPC_CLOSURE_INIT(&self->my_closure_, OnWatchCompleteLocked, self, + grpc_combiner_scheduler(self->chand_->combiner)); + grpc_connectivity_state_notify_on_state_change( + &self->chand_->state_tracker, self->state_, &self->my_closure_); +} + +// +// ClientChannelControlHelper +// class ClientChannelControlHelper : public LoadBalancingPolicy::ChannelControlHelper { @@ -222,8 +458,10 @@ class ClientChannelControlHelper void UpdateState( grpc_connectivity_state state, grpc_error* state_error, UniquePtr picker) override { + grpc_error* disconnect_error = + chand_->disconnect_error.Load(grpc_core::MemoryOrder::ACQUIRE); if (grpc_client_channel_routing_trace.enabled()) { - const char* extra = chand_->disconnect_error == GRPC_ERROR_NONE + const char* extra = disconnect_error == GRPC_ERROR_NONE ? "" : " (ignoring -- channel shutting down)"; gpr_log(GPR_INFO, "chand=%p: update: state=%s error=%s picker=%p%s", @@ -231,9 +469,10 @@ class ClientChannelControlHelper grpc_error_string(state_error), picker.get(), extra); } // Do update only if not shutting down. - if (chand_->disconnect_error == GRPC_ERROR_NONE) { - set_connectivity_state_and_picker_locked(chand_, state, state_error, - "helper", std::move(picker)); + if (disconnect_error == GRPC_ERROR_NONE) { + // Will delete itself. + New(chand_, state, state_error, + "helper", std::move(picker)); } else { GRPC_ERROR_UNREF(state_error); } @@ -255,7 +494,6 @@ static bool process_resolver_result_locked( void* arg, grpc_core::Resolver::Result* result, const char** lb_policy_name, grpc_core::RefCountedPtr* lb_policy_config) { channel_data* chand = static_cast(arg); - chand->have_service_config = true; ProcessedResolverResult resolver_result(result, chand->enable_retries); grpc_core::UniquePtr service_config_json = resolver_result.service_config_json(); @@ -263,9 +501,11 @@ static bool process_resolver_result_locked( gpr_log(GPR_INFO, "chand=%p: resolver returned service config: \"%s\"", chand, service_config_json.get()); } - // Update channel state. - chand->retry_throttle_data = resolver_result.retry_throttle_data(); - chand->method_params_table = resolver_result.method_params_table(); + // Create service config setter to update channel state in the data + // plane combiner. Destroys itself when done. + grpc_core::New( + chand, resolver_result.retry_throttle_data(), + resolver_result.method_params_table()); // Swap out the data used by cc_get_channel_info(). gpr_mu_lock(&chand->info_mu); chand->info_lb_policy_name = resolver_result.lb_policy_name(); @@ -280,11 +520,6 @@ static bool process_resolver_result_locked( // Return results. *lb_policy_name = chand->info_lb_policy_name.get(); *lb_policy_config = resolver_result.lb_policy_config(); - // Apply service config to queued picks. - for (QueuedPick* pick = chand->queued_picks; pick != nullptr; - pick = pick->next) { - maybe_apply_service_config_to_call_locked(pick->elem); - } return service_config_changed; } @@ -342,12 +577,16 @@ static void start_transport_op_locked(void* arg, grpc_error* error_ignored) { } if (op->disconnect_with_error != GRPC_ERROR_NONE) { - chand->disconnect_error = op->disconnect_with_error; + grpc_error* error = GRPC_ERROR_NONE; + GPR_ASSERT(chand->disconnect_error.CompareExchangeStrong( + &error, op->disconnect_with_error, grpc_core::MemoryOrder::ACQ_REL, + grpc_core::MemoryOrder::ACQUIRE)); grpc_pollset_set_del_pollset_set( chand->resolving_lb_policy->interested_parties(), chand->interested_parties); chand->resolving_lb_policy.reset(); - set_connectivity_state_and_picker_locked( + // Will delete itself. + grpc_core::New( chand, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(op->disconnect_with_error), "shutdown from API", grpc_core::UniquePtr( @@ -397,17 +636,14 @@ static grpc_error* cc_init_channel_elem(grpc_channel_element* elem, GPR_ASSERT(args->is_last); GPR_ASSERT(elem->filter == &grpc_client_channel_filter); // Initialize data members. + chand->data_plane_combiner = grpc_combiner_create(); chand->combiner = grpc_combiner_create(); grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_channel"); - chand->disconnect_error = GRPC_ERROR_NONE; + chand->disconnect_error.Store(GRPC_ERROR_NONE, + grpc_core::MemoryOrder::RELAXED); gpr_mu_init(&chand->info_mu); - gpr_mu_init(&chand->external_connectivity_watcher_list_mu); - - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - chand->external_connectivity_watcher_list_head = nullptr; - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - + chand->external_connectivity_watcher_list.Init(); chand->owning_stack = args->channel_stack; chand->deadline_checking_enabled = grpc_deadline_checking_enabled(args->channel_args); @@ -511,11 +747,13 @@ static void cc_destroy_channel_elem(grpc_channel_element* elem) { chand->method_params_table.reset(); grpc_client_channel_stop_backup_polling(chand->interested_parties); grpc_pollset_set_destroy(chand->interested_parties); + GRPC_COMBINER_UNREF(chand->data_plane_combiner, "client_channel"); GRPC_COMBINER_UNREF(chand->combiner, "client_channel"); - GRPC_ERROR_UNREF(chand->disconnect_error); + GRPC_ERROR_UNREF( + chand->disconnect_error.Load(grpc_core::MemoryOrder::RELAXED)); grpc_connectivity_state_destroy(&chand->state_tracker); gpr_mu_destroy(&chand->info_mu); - gpr_mu_destroy(&chand->external_connectivity_watcher_list_mu); + chand->external_connectivity_watcher_list.Destroy(); } /************************************************************************* @@ -1261,7 +1499,7 @@ static void do_retry(grpc_call_element* elem, } // Schedule retry after computed delay. GRPC_CLOSURE_INIT(&calld->pick_closure, start_pick_locked, elem, - grpc_combiner_scheduler(chand->combiner)); + grpc_combiner_scheduler(chand->data_plane_combiner)); grpc_timer_init(&calld->retry_timer, next_attempt_time, &calld->pick_closure); // Update bookkeeping. if (retry_state != nullptr) retry_state->retry_dispatched = true; @@ -2488,7 +2726,7 @@ class QueuedPickCanceller { auto* chand = static_cast(elem->channel_data); GRPC_CALL_STACK_REF(calld->owning_call, "QueuedPickCanceller"); GRPC_CLOSURE_INIT(&closure_, &CancelLocked, this, - grpc_combiner_scheduler(chand->combiner)); + grpc_combiner_scheduler(chand->data_plane_combiner)); grpc_call_combiner_set_notify_on_cancel(calld->call_combiner, &closure_); } @@ -2628,7 +2866,7 @@ static void maybe_apply_service_config_to_call_locked(grpc_call_element* elem) { call_data* calld = static_cast(elem->call_data); // Apply service config data to the call only once, and only if the // channel has the data available. - if (GPR_LIKELY(chand->have_service_config && + if (GPR_LIKELY(chand->received_service_config_data && !calld->service_config_applied)) { calld->service_config_applied = true; apply_service_config_to_call_locked(elem); @@ -2676,7 +2914,7 @@ static void start_pick_locked(void* arg, grpc_error* error) { .send_initial_metadata_flags; // Apply service config to call if needed. maybe_apply_service_config_to_call_locked(elem); - // When done, we schedule this closure to leave the channel combiner. + // When done, we schedule this closure to leave the data plane combiner. GRPC_CLOSURE_INIT(&calld->pick_closure, pick_done, elem, grpc_schedule_on_exec_ctx); // Attempt pick. @@ -2691,12 +2929,14 @@ static void start_pick_locked(void* arg, grpc_error* error) { grpc_error_string(error)); } switch (pick_result) { - case LoadBalancingPolicy::PICK_TRANSIENT_FAILURE: + case LoadBalancingPolicy::PICK_TRANSIENT_FAILURE: { // If we're shutting down, fail all RPCs. - if (chand->disconnect_error != GRPC_ERROR_NONE) { + grpc_error* disconnect_error = + chand->disconnect_error.Load(grpc_core::MemoryOrder::ACQUIRE); + if (disconnect_error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(error); GRPC_CLOSURE_SCHED(&calld->pick_closure, - GRPC_ERROR_REF(chand->disconnect_error)); + GRPC_ERROR_REF(disconnect_error)); break; } // If wait_for_ready is false, then the error indicates the RPC @@ -2722,7 +2962,8 @@ static void start_pick_locked(void* arg, grpc_error* error) { // If wait_for_ready is true, then queue to retry when we get a new // picker. GRPC_ERROR_UNREF(error); - // Fallthrough + } + // Fallthrough case LoadBalancingPolicy::PICK_QUEUE: if (!calld->pick_queued) add_call_to_queued_picks_locked(elem); break; @@ -2816,7 +3057,8 @@ static void cc_start_transport_stream_op_batch( } GRPC_CLOSURE_SCHED( GRPC_CLOSURE_INIT(&batch->handler_private.closure, start_pick_locked, - elem, grpc_combiner_scheduler(chand->combiner)), + elem, + grpc_combiner_scheduler(chand->data_plane_combiner)), GRPC_ERROR_NONE); } else { // For all other batches, release the call combiner. @@ -2875,6 +3117,10 @@ const grpc_channel_filter grpc_client_channel_filter = { "client-channel", }; +// +// functions exported to the rest of core +// + void grpc_client_channel_set_channelz_node( grpc_channel_element* elem, grpc_core::channelz::ClientChannelNode* node) { channel_data* chand = static_cast(elem->channel_data); @@ -2914,120 +3160,10 @@ grpc_connectivity_state grpc_client_channel_check_connectivity_state( return out; } -typedef struct external_connectivity_watcher { - channel_data* chand; - grpc_polling_entity pollent; - grpc_closure* on_complete; - grpc_closure* watcher_timer_init; - grpc_connectivity_state* state; - grpc_closure my_closure; - struct external_connectivity_watcher* next; -} external_connectivity_watcher; - -static external_connectivity_watcher* lookup_external_connectivity_watcher( - channel_data* chand, grpc_closure* on_complete) { - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - external_connectivity_watcher* w = - chand->external_connectivity_watcher_list_head; - while (w != nullptr && w->on_complete != on_complete) { - w = w->next; - } - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - return w; -} - -static void external_connectivity_watcher_list_append( - channel_data* chand, external_connectivity_watcher* w) { - GPR_ASSERT(!lookup_external_connectivity_watcher(chand, w->on_complete)); - - gpr_mu_lock(&w->chand->external_connectivity_watcher_list_mu); - GPR_ASSERT(!w->next); - w->next = chand->external_connectivity_watcher_list_head; - chand->external_connectivity_watcher_list_head = w; - gpr_mu_unlock(&w->chand->external_connectivity_watcher_list_mu); -} - -static void external_connectivity_watcher_list_remove( - channel_data* chand, external_connectivity_watcher* to_remove) { - GPR_ASSERT( - lookup_external_connectivity_watcher(chand, to_remove->on_complete)); - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - if (to_remove == chand->external_connectivity_watcher_list_head) { - chand->external_connectivity_watcher_list_head = to_remove->next; - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - return; - } - external_connectivity_watcher* w = - chand->external_connectivity_watcher_list_head; - while (w != nullptr) { - if (w->next == to_remove) { - w->next = w->next->next; - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - return; - } - w = w->next; - } - GPR_UNREACHABLE_CODE(return ); -} - int grpc_client_channel_num_external_connectivity_watchers( grpc_channel_element* elem) { channel_data* chand = static_cast(elem->channel_data); - int count = 0; - - gpr_mu_lock(&chand->external_connectivity_watcher_list_mu); - external_connectivity_watcher* w = - chand->external_connectivity_watcher_list_head; - while (w != nullptr) { - count++; - w = w->next; - } - gpr_mu_unlock(&chand->external_connectivity_watcher_list_mu); - - return count; -} - -static void on_external_watch_complete_locked(void* arg, grpc_error* error) { - external_connectivity_watcher* w = - static_cast(arg); - grpc_closure* follow_up = w->on_complete; - grpc_polling_entity_del_from_pollset_set(&w->pollent, - w->chand->interested_parties); - GRPC_CHANNEL_STACK_UNREF(w->chand->owning_stack, - "external_connectivity_watcher"); - external_connectivity_watcher_list_remove(w->chand, w); - gpr_free(w); - GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); -} - -static void watch_connectivity_state_locked(void* arg, - grpc_error* error_ignored) { - external_connectivity_watcher* w = - static_cast(arg); - external_connectivity_watcher* found = nullptr; - if (w->state != nullptr) { - external_connectivity_watcher_list_append(w->chand, w); - // An assumption is being made that the closure is scheduled on the exec ctx - // scheduler and that GRPC_CLOSURE_RUN would run the closure immediately. - GRPC_CLOSURE_RUN(w->watcher_timer_init, GRPC_ERROR_NONE); - GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete_locked, w, - grpc_combiner_scheduler(w->chand->combiner)); - grpc_connectivity_state_notify_on_state_change(&w->chand->state_tracker, - w->state, &w->my_closure); - } else { - GPR_ASSERT(w->watcher_timer_init == nullptr); - found = lookup_external_connectivity_watcher(w->chand, w->on_complete); - if (found) { - GPR_ASSERT(found->on_complete == w->on_complete); - grpc_connectivity_state_notify_on_state_change( - &found->chand->state_tracker, nullptr, &found->my_closure); - } - grpc_polling_entity_del_from_pollset_set(&w->pollent, - w->chand->interested_parties); - GRPC_CHANNEL_STACK_UNREF(w->chand->owning_stack, - "external_connectivity_watcher"); - gpr_free(w); - } + return chand->external_connectivity_watcher_list->size(); } void grpc_client_channel_watch_connectivity_state( @@ -3035,21 +3171,8 @@ void grpc_client_channel_watch_connectivity_state( grpc_connectivity_state* state, grpc_closure* closure, grpc_closure* watcher_timer_init) { channel_data* chand = static_cast(elem->channel_data); - external_connectivity_watcher* w = - static_cast(gpr_zalloc(sizeof(*w))); - w->chand = chand; - w->pollent = pollent; - w->on_complete = closure; - w->state = state; - w->watcher_timer_init = watcher_timer_init; - grpc_polling_entity_add_to_pollset_set(&w->pollent, - chand->interested_parties); - GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, - "external_connectivity_watcher"); - GRPC_CLOSURE_SCHED( - GRPC_CLOSURE_INIT(&w->my_closure, watch_connectivity_state_locked, w, - grpc_combiner_scheduler(chand->combiner)), - GRPC_ERROR_NONE); + grpc_core::New( + chand, pollent, state, closure, watcher_timer_init); } grpc_core::RefCountedPtr diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc index 2031ab449f5..8e76c4cbb15 100644 --- a/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -49,6 +49,7 @@ static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { } void grpc_client_channel_init(void) { + grpc_core::ServiceConfig::Init(); grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry(); grpc_core::ResolverRegistry::Builder::InitRegistry(); grpc_core::internal::ServerRetryThrottleMap::Init(); @@ -68,4 +69,5 @@ void grpc_client_channel_shutdown(void) { grpc_core::internal::ServerRetryThrottleMap::Shutdown(); grpc_core::ResolverRegistry::Builder::ShutdownRegistry(); grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry(); + grpc_core::ServiceConfig::Shutdown(); } diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index e845d63d295..a22d6450cbd 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -287,7 +287,6 @@ HealthCheckClient::CallState::CallState( ->GetInitialCallSizeEstimate(0))), payload_(context_) { grpc_call_combiner_init(&call_combiner_); - gpr_atm_rel_store(&seen_response_, static_cast(0)); } HealthCheckClient::CallState::~CallState() { @@ -295,9 +294,6 @@ HealthCheckClient::CallState::~CallState() { gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", health_check_client_.get(), this); } - // The subchannel call is in the arena, so reset the pointer before we destroy - // the arena. - call_.reset(); for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (context_[i].destroy != nullptr) { context_[i].destroy(context_[i].value); @@ -349,7 +345,6 @@ void HealthCheckClient::CallState::StartCall() { return; } // Initialize payload and batch. - memset(&batch_, 0, sizeof(batch_)); payload_.context = context_; batch_.payload = &payload_; // on_complete callback takes ref, handled manually. @@ -401,8 +396,6 @@ void HealthCheckClient::CallState::StartCall() { // Start batch. StartBatch(&batch_); // Initialize recv_trailing_metadata batch. - memset(&recv_trailing_metadata_batch_, 0, - sizeof(recv_trailing_metadata_batch_)); recv_trailing_metadata_batch_.payload = &payload_; // Add recv_trailing_metadata op. grpc_metadata_batch_init(&recv_trailing_metadata_); @@ -439,12 +432,22 @@ void HealthCheckClient::CallState::StartBatch( GRPC_ERROR_NONE, "start_subchannel_batch"); } +void HealthCheckClient::CallState::AfterCallStackDestruction( + void* arg, grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + self->Unref(DEBUG_LOCATION, "cancel"); +} + void HealthCheckClient::CallState::OnCancelComplete(void* arg, grpc_error* error) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "health_cancel"); - self->Unref(DEBUG_LOCATION, "cancel"); + GRPC_CLOSURE_INIT(&self->after_call_stack_destruction_, + AfterCallStackDestruction, self, grpc_schedule_on_exec_ctx); + self->call_->SetAfterCallStackDestroy(&self->after_call_stack_destruction_); + self->call_.reset(); } void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { @@ -458,7 +461,9 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { } void HealthCheckClient::CallState::Cancel() { - if (call_ != nullptr) { + bool expected = false; + if (cancelled_.CompareExchangeStrong(&expected, true, MemoryOrder::ACQ_REL, + MemoryOrder::ACQUIRE)) { Ref(DEBUG_LOCATION, "cancel").release(); GRPC_CALL_COMBINER_START( &call_combiner_, @@ -501,13 +506,12 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("backend unhealthy"); } health_check_client_->SetHealthStatus(state, error); - gpr_atm_rel_store(&seen_response_, static_cast(1)); + seen_response_.Store(true, MemoryOrder::RELEASE); grpc_slice_buffer_destroy_internal(&recv_message_buffer_); // Start another recv_message batch. // This re-uses the ref we're holding. // Note: Can't just reuse batch_ here, since we don't know that all // callbacks from the original batch have completed yet. - memset(&recv_message_batch_, 0, sizeof(recv_message_batch_)); recv_message_batch_.payload = &payload_; payload_.recv_message.recv_message = &recv_message_; payload_.recv_message.recv_message_ready = GRPC_CLOSURE_INIT( @@ -635,7 +639,7 @@ void HealthCheckClient::CallState::CallEnded(bool retry) { health_check_client_->call_state_.reset(); if (retry) { GPR_ASSERT(!health_check_client_->shutting_down_); - if (static_cast(gpr_atm_acq_load(&seen_response_))) { + if (seen_response_.Load(MemoryOrder::ACQUIRE)) { // If the call fails after we've gotten a successful response, reset // the backoff and restart the call immediately. health_check_client_->retry_backoff_.Reset(); diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 7af88a54cfc..1fa4487c403 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -22,13 +22,13 @@ #include #include -#include #include #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/gpr/arena.h" +#include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/call_combiner.h" @@ -91,6 +91,8 @@ class HealthCheckClient : public InternallyRefCounted { grpc_error* PullSliceFromRecvMessage(); void DoneReadingRecvMessage(grpc_error* error); + static void AfterCallStackDestruction(void* arg, grpc_error* error); + RefCountedPtr health_check_client_; grpc_polling_entity pollent_; @@ -126,12 +128,18 @@ class HealthCheckClient : public InternallyRefCounted { OrphanablePtr recv_message_; grpc_closure recv_message_ready_; grpc_slice_buffer recv_message_buffer_; - gpr_atm seen_response_; + Atomic seen_response_{false}; // recv_trailing_metadata grpc_metadata_batch recv_trailing_metadata_; grpc_transport_stream_stats collect_stats_; grpc_closure recv_trailing_metadata_ready_; + + // True if the cancel_stream batch has been started. + Atomic cancelled_{false}; + + // Closure for call stack destruction. + grpc_closure after_call_stack_destruction_; }; void StartCall(); diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc index c8f8e82e5d7..6b657465891 100644 --- a/src/core/ext/filters/client_channel/lb_policy.cc +++ b/src/core/ext/filters/client_channel/lb_policy.cc @@ -140,10 +140,9 @@ LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick( // the time this function returns, the pick will already have // been processed, and we'll be trying to re-process the same // pick again, leading to a crash. - // 2. In a subsequent PR, we will split the data plane and control - // plane synchronization into separate combiners, at which - // point this will need to hop from the data plane combiner into - // the control plane combiner. + // 2. We are currently running in the data plane combiner, but we + // need to bounce into the control plane combiner to call + // ExitIdleLocked(). if (!exit_idle_called_) { exit_idle_called_ = true; parent_->Ref().release(); // ref held by closure. diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 02fe06c4557..aebd2fd3faa 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -234,12 +234,19 @@ class GrpcLb : public LoadBalancingPolicy { // Returns the LB token to use for a drop, or null if the call // should not be dropped. - // Intended to be called from picker, so calls will be externally - // synchronized. + // + // Note: This is called from the picker, so it will be invoked in + // the channel's data plane combiner, NOT the control plane + // combiner. It should not be accessed by any other part of the LB + // policy. const char* ShouldDrop(); private: grpc_grpclb_serverlist* serverlist_; + + // Guarded by the channel's data plane combiner, NOT the control + // plane combiner. It should not be accessed by anything but the + // picker via the ShouldDrop() method. size_t drop_index_ = 0; }; @@ -551,7 +558,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs* pick, grpc_error** error) { // subchannel call (and therefore no client_load_reporting filter) // for dropped calls. if (client_stats_ != nullptr) { - client_stats_->AddCallDroppedLocked(drop_token); + client_stats_->AddCallDropped(drop_token); } return PICK_COMPLETE; } @@ -910,7 +917,7 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() { // Construct message payload. GPR_ASSERT(send_message_payload_ == nullptr); grpc_grpclb_request* request = - grpc_grpclb_load_report_request_create_locked(client_stats_.get()); + grpc_grpclb_load_report_request_create(client_stats_.get()); // Skip client load report if the counters were all zero in the last // report and they are still zero in this one. if (LoadReportCountersAreZero(request)) { diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc index 1c7ed871d74..84b9c41a734 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc @@ -25,6 +25,8 @@ #include #include +#include "src/core/lib/gprpp/mutex_lock.h" + namespace grpc_core { void GrpcLbClientStats::AddCallStarted() { @@ -43,11 +45,12 @@ void GrpcLbClientStats::AddCallFinished( } } -void GrpcLbClientStats::AddCallDroppedLocked(const char* token) { +void GrpcLbClientStats::AddCallDropped(const char* token) { // Increment num_calls_started and num_calls_finished. gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1); gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1); // Record the drop. + MutexLock lock(&drop_count_mu_); if (drop_token_counts_ == nullptr) { drop_token_counts_.reset(New()); } @@ -69,7 +72,7 @@ void AtomicGetAndResetCounter(int64_t* value, gpr_atm* counter) { } // namespace -void GrpcLbClientStats::GetLocked( +void GrpcLbClientStats::Get( int64_t* num_calls_started, int64_t* num_calls_finished, int64_t* num_calls_finished_with_client_failed_to_send, int64_t* num_calls_finished_known_received, @@ -80,6 +83,7 @@ void GrpcLbClientStats::GetLocked( &num_calls_finished_with_client_failed_to_send_); AtomicGetAndResetCounter(num_calls_finished_known_received, &num_calls_finished_known_received_); + MutexLock lock(&drop_count_mu_); *drop_token_counts = std::move(drop_token_counts_); } diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index cb261ee16c7..fdebdf55c17 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -41,20 +41,19 @@ class GrpcLbClientStats : public RefCounted { typedef InlinedVector DroppedCallCounts; - GrpcLbClientStats() {} + GrpcLbClientStats() { gpr_mu_init(&drop_count_mu_); } + ~GrpcLbClientStats() { gpr_mu_destroy(&drop_count_mu_); } void AddCallStarted(); void AddCallFinished(bool finished_with_client_failed_to_send, bool finished_known_received); - // This method is not thread-safe; caller must synchronize. - void AddCallDroppedLocked(const char* token); + void AddCallDropped(const char* token); - // This method is not thread-safe; caller must synchronize. - void GetLocked(int64_t* num_calls_started, int64_t* num_calls_finished, - int64_t* num_calls_finished_with_client_failed_to_send, - int64_t* num_calls_finished_known_received, - UniquePtr* drop_token_counts); + void Get(int64_t* num_calls_started, int64_t* num_calls_finished, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received, + UniquePtr* drop_token_counts); // A destruction function to use as the user_data key when attaching // client stats to a grpc_mdelem. @@ -63,13 +62,12 @@ class GrpcLbClientStats : public RefCounted { } private: - // This field must only be accessed via *_locked() methods. - UniquePtr drop_token_counts_; - // These fields may be accessed from multiple threads at a time. gpr_atm num_calls_started_ = 0; gpr_atm num_calls_finished_ = 0; gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; gpr_atm num_calls_finished_known_received_ = 0; + gpr_mu drop_count_mu_; // Guards drop_token_counts_. + UniquePtr drop_token_counts_; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc index 594c8cf6e94..b51db110395 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc @@ -107,7 +107,7 @@ static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field, return true; } -grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( +grpc_grpclb_request* grpc_grpclb_load_report_request_create( grpc_core::GrpcLbClientStats* client_stats) { grpc_grpclb_request* req = static_cast( gpr_zalloc(sizeof(grpc_grpclb_request))); @@ -122,7 +122,7 @@ grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( req->client_stats.calls_finished_with_drop.funcs.encode = encode_drops; grpc_core::UniquePtr drop_counts; - client_stats->GetLocked( + client_stats->Get( &req->client_stats.num_calls_started, &req->client_stats.num_calls_finished, &req->client_stats.num_calls_finished_with_client_failed_to_send, diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h index 3c1d41a01b1..8005f6fe301 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h @@ -43,7 +43,7 @@ typedef struct { /** Create a request for a gRPC LB service under \a lb_service_name */ grpc_grpclb_request* grpc_grpclb_request_create(const char* lb_service_name); -grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( +grpc_grpclb_request* grpc_grpclb_load_report_request_create( grpc_core::GrpcLbClientStats* client_stats); /** Protocol Buffers v3-encode \a request */ diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 86c6b25ac63..332f66808e0 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -186,10 +186,17 @@ void PickFirst::ShutdownLocked() { } void PickFirst::ExitIdleLocked() { + if (shutdown_) return; if (idle_) { idle_ = false; - if (subchannel_list_ != nullptr && - subchannel_list_->num_subchannels() > 0) { + if (subchannel_list_ == nullptr || + subchannel_list_->num_subchannels() == 0) { + grpc_error* error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No addresses to connect to"); + channel_control_helper()->UpdateState( + GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), + UniquePtr(New(error))); + } else { subchannel_list_->subchannel(0) ->CheckConnectivityStateAndStartWatchingLocked(); } @@ -253,13 +260,19 @@ void PickFirst::UpdateLocked(UpdateArgs args) { grpc_channel_args_destroy(new_args); if (subchannel_list->num_subchannels() == 0) { // Empty update or no valid subchannels. Unsubscribe from all current - // subchannels and put the channel in TRANSIENT_FAILURE. + // subchannels. subchannel_list_ = std::move(subchannel_list); // Empty list. selected_ = nullptr; - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"); - channel_control_helper()->UpdateState( - GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), - UniquePtr(New(error))); + // If not idle, put the channel in TRANSIENT_FAILURE. + // (If we are idle, then this will happen in ExitIdleLocked() if we + // haven't gotten a non-empty update by the time the application tries + // to start a new call.) + if (!idle_) { + grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"); + channel_control_helper()->UpdateState( + GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(error), + UniquePtr(New(error))); + } return; } // If one of the subchannels in the new list is already in state diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc index d3b13a60ebf..fe49e9aca03 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc @@ -68,7 +68,9 @@ #include #include +#include "include/grpc/support/alloc.h" #include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy.h" #include "src/core/ext/filters/client_channel/lb_policy/xds/xds.h" #include "src/core/ext/filters/client_channel/lb_policy/xds/xds_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/xds/xds_client_stats.h" @@ -85,6 +87,7 @@ #include "src/core/lib/gpr/host_port.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/gprpp/map.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" @@ -114,6 +117,7 @@ TraceFlag grpc_lb_xds_trace(false, "xds"); namespace { constexpr char kXds[] = "xds_experimental"; +constexpr char kDefaultLocalityName[] = "xds_default_locality"; class XdsLb : public LoadBalancingPolicy { public: @@ -128,6 +132,9 @@ class XdsLb : public LoadBalancingPolicy { channelz::ChildRefsList* child_channels) override; private: + struct LocalityServerlistEntry; + using LocalityList = InlinedVector, 1>; + /// Contains a channel to the LB server and all the data related to the /// channel. class BalancerChannelState @@ -266,25 +273,88 @@ class XdsLb : public LoadBalancingPolicy { RefCountedPtr client_stats_; }; - class Helper : public ChannelControlHelper { + class LocalityMap { public: - explicit Helper(RefCountedPtr parent) : parent_(std::move(parent)) {} + class LocalityEntry : public InternallyRefCounted { + public: + explicit LocalityEntry(RefCountedPtr parent) + : parent_(std::move(parent)) { + gpr_mu_init(&child_policy_mu_); + } + ~LocalityEntry() { gpr_mu_destroy(&child_policy_mu_); } + + void UpdateLocked(xds_grpclb_serverlist* serverlist, + LoadBalancingPolicy::Config* child_policy_config, + const grpc_channel_args* args); + void ShutdownLocked(); + void ResetBackoffLocked(); + void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels); + void Orphan() override; + + private: + class Helper : public ChannelControlHelper { + public: + explicit Helper(RefCountedPtr entry) + : entry_(std::move(entry)) {} + + Subchannel* CreateSubchannel(const grpc_channel_args& args) override; + grpc_channel* CreateChannel(const char* target, + const grpc_channel_args& args) override; + void UpdateState(grpc_connectivity_state state, grpc_error* state_error, + UniquePtr picker) override; + void RequestReresolution() override; + void set_child(LoadBalancingPolicy* child) { child_ = child; } + + private: + bool CalledByPendingChild() const; + bool CalledByCurrentChild() const; + + RefCountedPtr entry_; + LoadBalancingPolicy* child_ = nullptr; + }; + // Methods for dealing with the child policy. + OrphanablePtr CreateChildPolicyLocked( + const char* name, const grpc_channel_args* args); + grpc_channel_args* CreateChildPolicyArgsLocked( + const grpc_channel_args* args); + + OrphanablePtr child_policy_; + OrphanablePtr pending_child_policy_; + // Lock held when modifying the value of child_policy_ or + // pending_child_policy_. + gpr_mu child_policy_mu_; + RefCountedPtr parent_; + }; - Subchannel* CreateSubchannel(const grpc_channel_args& args) override; - grpc_channel* CreateChannel(const char* target, - const grpc_channel_args& args) override; - void UpdateState(grpc_connectivity_state state, grpc_error* state_error, - UniquePtr picker) override; - void RequestReresolution() override; + LocalityMap() { gpr_mu_init(&child_refs_mu_); } + ~LocalityMap() { gpr_mu_destroy(&child_refs_mu_); } - void set_child(LoadBalancingPolicy* child) { child_ = child; } + void UpdateLocked(const LocalityList& locality_list, + LoadBalancingPolicy::Config* child_policy_config, + const grpc_channel_args* args, XdsLb* parent); + void ShutdownLocked(); + void ResetBackoffLocked(); + void FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels); private: - bool CalledByPendingChild() const; - bool CalledByCurrentChild() const; + void PruneLocalities(const LocalityList& locality_list); + Map, OrphanablePtr, StringLess> map_; + // Lock held while filling child refs for all localities + // inside the map + gpr_mu child_refs_mu_; + }; - RefCountedPtr parent_; - LoadBalancingPolicy* child_ = nullptr; + struct LocalityServerlistEntry { + ~LocalityServerlistEntry() { + gpr_free(locality_name); + xds_grpclb_destroy_serverlist(serverlist); + } + char* locality_name; + // The deserialized response from the balancer. May be nullptr until one + // such response has arrived. + xds_grpclb_serverlist* serverlist; }; ~XdsLb(); @@ -309,12 +379,6 @@ class XdsLb : public LoadBalancingPolicy { // Callback to enter fallback mode. static void OnFallbackTimerLocked(void* arg, grpc_error* error); - // Methods for dealing with the child policy. - void CreateOrUpdateChildPolicyLocked(); - grpc_channel_args* CreateChildPolicyArgsLocked(); - OrphanablePtr CreateChildPolicyLocked( - const char* name, const grpc_channel_args* args); - // Who the client is trying to communicate with. const char* server_name_ = nullptr; @@ -338,10 +402,6 @@ class XdsLb : public LoadBalancingPolicy { // Timeout in milliseconds for the LB call. 0 means no deadline. int lb_call_timeout_ms_ = 0; - // The deserialized response from the balancer. May be nullptr until one - // such response has arrived. - xds_grpclb_serverlist* serverlist_ = nullptr; - // Timeout in milliseconds for before using fallback backend addresses. // 0 means not using fallback. RefCountedPtr fallback_policy_config_; @@ -355,11 +415,12 @@ class XdsLb : public LoadBalancingPolicy { // The policy to use for the backends. RefCountedPtr child_policy_config_; - OrphanablePtr child_policy_; - OrphanablePtr pending_child_policy_; - // Lock held when modifying the value of child_policy_ or - // pending_child_policy_. - gpr_mu child_policy_mu_; + // Map of policies to use in the backend + LocalityMap locality_map_; + LocalityList locality_serverlist_; + // TODO(mhaidry) : Add a pending locality map that may be swapped with the + // the current one when new localities in the pending map are ready + // to accept connections }; // @@ -378,105 +439,6 @@ XdsLb::PickResult XdsLb::Picker::Pick(PickArgs* pick, grpc_error** error) { return result; } -// -// XdsLb::Helper -// - -bool XdsLb::Helper::CalledByPendingChild() const { - GPR_ASSERT(child_ != nullptr); - return child_ == parent_->pending_child_policy_.get(); -} - -bool XdsLb::Helper::CalledByCurrentChild() const { - GPR_ASSERT(child_ != nullptr); - return child_ == parent_->child_policy_.get(); -} - -Subchannel* XdsLb::Helper::CreateSubchannel(const grpc_channel_args& args) { - if (parent_->shutting_down_ || - (!CalledByPendingChild() && !CalledByCurrentChild())) { - return nullptr; - } - return parent_->channel_control_helper()->CreateSubchannel(args); -} - -grpc_channel* XdsLb::Helper::CreateChannel(const char* target, - const grpc_channel_args& args) { - if (parent_->shutting_down_ || - (!CalledByPendingChild() && !CalledByCurrentChild())) { - return nullptr; - } - return parent_->channel_control_helper()->CreateChannel(target, args); -} - -void XdsLb::Helper::UpdateState(grpc_connectivity_state state, - grpc_error* state_error, - UniquePtr picker) { - if (parent_->shutting_down_) { - GRPC_ERROR_UNREF(state_error); - return; - } - // If this request is from the pending child policy, ignore it until - // it reports READY, at which point we swap it into place. - if (CalledByPendingChild()) { - if (grpc_lb_xds_trace.enabled()) { - gpr_log(GPR_INFO, - "[xdslb %p helper %p] pending child policy %p reports state=%s", - parent_.get(), this, parent_->pending_child_policy_.get(), - grpc_connectivity_state_name(state)); - } - if (state != GRPC_CHANNEL_READY) { - GRPC_ERROR_UNREF(state_error); - return; - } - grpc_pollset_set_del_pollset_set( - parent_->child_policy_->interested_parties(), - parent_->interested_parties()); - MutexLock lock(&parent_->child_policy_mu_); - parent_->child_policy_ = std::move(parent_->pending_child_policy_); - } else if (!CalledByCurrentChild()) { - // This request is from an outdated child, so ignore it. - GRPC_ERROR_UNREF(state_error); - return; - } - // TODO(juanlishen): When in fallback mode, pass the child picker - // through without wrapping it. (Or maybe use a different helper for - // the fallback policy?) - GPR_ASSERT(parent_->lb_chand_ != nullptr); - RefCountedPtr client_stats = - parent_->lb_chand_->lb_calld() == nullptr - ? nullptr - : parent_->lb_chand_->lb_calld()->client_stats(); - parent_->channel_control_helper()->UpdateState( - state, state_error, - UniquePtr( - New(std::move(picker), std::move(client_stats)))); -} - -void XdsLb::Helper::RequestReresolution() { - if (parent_->shutting_down_) return; - // If there is a pending child policy, ignore re-resolution requests - // from the current child policy (or any outdated child). - if (parent_->pending_child_policy_ != nullptr && !CalledByPendingChild()) { - return; - } - if (grpc_lb_xds_trace.enabled()) { - gpr_log(GPR_INFO, - "[xdslb %p] Re-resolution requested from the internal RR policy " - "(%p).", - parent_.get(), parent_->child_policy_.get()); - } - GPR_ASSERT(parent_->lb_chand_ != nullptr); - // If we are talking to a balancer, we expect to get updated addresses - // from the balancer, so we can ignore the re-resolution request from - // the child policy. Otherwise, pass the re-resolution request up to the - // channel. - if (parent_->lb_chand_->lb_calld() == nullptr || - !parent_->lb_chand_->lb_calld()->seen_initial_response()) { - parent_->channel_control_helper()->RequestReresolution(); - } -} - // // serverlist parsing code // @@ -951,7 +913,9 @@ void XdsLb::BalancerChannelState::BalancerCallState:: self.release(); lb_calld->ScheduleNextClientLoadReportLocked(); } - if (xds_grpclb_serverlist_equals(xdslb_policy->serverlist_, serverlist)) { + if (!xdslb_policy->locality_serverlist_.empty() && + xds_grpclb_serverlist_equals( + xdslb_policy->locality_serverlist_[0]->serverlist, serverlist)) { if (grpc_lb_xds_trace.enabled()) { gpr_log(GPR_INFO, "[xdslb %p] Incoming server list identical to current, " @@ -960,21 +924,31 @@ void XdsLb::BalancerChannelState::BalancerCallState:: } xds_grpclb_destroy_serverlist(serverlist); } else { /* new serverlist */ - if (xdslb_policy->serverlist_ != nullptr) { + if (!xdslb_policy->locality_serverlist_.empty()) { /* dispose of the old serverlist */ - xds_grpclb_destroy_serverlist(xdslb_policy->serverlist_); + xds_grpclb_destroy_serverlist( + xdslb_policy->locality_serverlist_[0]->serverlist); } else { /* or dispose of the fallback */ xdslb_policy->fallback_backend_addresses_.reset(); if (xdslb_policy->fallback_timer_callback_pending_) { grpc_timer_cancel(&xdslb_policy->lb_fallback_timer_); } + /* Initialize locality serverlist, currently the list only handles + * one child */ + xdslb_policy->locality_serverlist_.emplace_back( + MakeUnique()); + xdslb_policy->locality_serverlist_[0]->locality_name = + static_cast(gpr_strdup(kDefaultLocalityName)); } // and update the copy in the XdsLb instance. This // serverlist instance will be destroyed either upon the next // update or when the XdsLb instance is destroyed. - xdslb_policy->serverlist_ = serverlist; - xdslb_policy->CreateOrUpdateChildPolicyLocked(); + xdslb_policy->locality_serverlist_[0]->serverlist = serverlist; + xdslb_policy->locality_map_.UpdateLocked( + xdslb_policy->locality_serverlist_, + xdslb_policy->child_policy_config_.get(), xdslb_policy->args_, + xdslb_policy); } } else { if (grpc_lb_xds_trace.enabled()) { @@ -1112,9 +1086,11 @@ grpc_channel_args* BuildBalancerChannelArgs(const grpc_channel_args* args) { // ctor and dtor // -XdsLb::XdsLb(Args args) : LoadBalancingPolicy(std::move(args)) { +XdsLb::XdsLb(Args args) + : LoadBalancingPolicy(std::move(args)), + locality_map_(), + locality_serverlist_() { gpr_mu_init(&lb_chand_mu_); - gpr_mu_init(&child_policy_mu_); // Record server name. const grpc_arg* arg = grpc_channel_args_find(args.args, GRPC_ARG_SERVER_URI); const char* server_uri = grpc_channel_arg_get_string(arg); @@ -1141,10 +1117,7 @@ XdsLb::~XdsLb() { gpr_mu_destroy(&lb_chand_mu_); gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); - if (serverlist_ != nullptr) { - xds_grpclb_destroy_serverlist(serverlist_); - } - gpr_mu_destroy(&child_policy_mu_); + locality_serverlist_.clear(); } void XdsLb::ShutdownLocked() { @@ -1152,19 +1125,7 @@ void XdsLb::ShutdownLocked() { if (fallback_timer_callback_pending_) { grpc_timer_cancel(&lb_fallback_timer_); } - if (child_policy_ != nullptr) { - grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(), - interested_parties()); - } - if (pending_child_policy_ != nullptr) { - grpc_pollset_set_del_pollset_set( - pending_child_policy_->interested_parties(), interested_parties()); - } - { - MutexLock lock(&child_policy_mu_); - child_policy_.reset(); - pending_child_policy_.reset(); - } + locality_map_.ShutdownLocked(); // We destroy the LB channel here instead of in our destructor because // destroying the channel triggers a last callback to // OnBalancerChannelConnectivityChangedLocked(), and we need to be @@ -1187,30 +1148,13 @@ void XdsLb::ResetBackoffLocked() { if (pending_lb_chand_ != nullptr) { grpc_channel_reset_connect_backoff(pending_lb_chand_->channel()); } - if (child_policy_ != nullptr) { - child_policy_->ResetBackoffLocked(); - } - if (pending_child_policy_ != nullptr) { - pending_child_policy_->ResetBackoffLocked(); - } + locality_map_.ResetBackoffLocked(); } void XdsLb::FillChildRefsForChannelz(channelz::ChildRefsList* child_subchannels, channelz::ChildRefsList* child_channels) { - { - // Delegate to the child_policy_ to fill the children subchannels. - // This must be done holding child_policy_mu_, since this method does not - // run in the combiner. - MutexLock lock(&child_policy_mu_); - if (child_policy_ != nullptr) { - child_policy_->FillChildRefsForChannelz(child_subchannels, - child_channels); - } - if (pending_child_policy_ != nullptr) { - pending_child_policy_->FillChildRefsForChannelz(child_subchannels, - child_channels); - } - } + // Delegate to the child_policy_ to fill the children subchannels. + locality_map_.FillChildRefsForChannelz(child_subchannels, child_channels); MutexLock lock(&lb_chand_mu_); if (lb_chand_ != nullptr) { grpc_core::channelz::ChannelNode* channel_node = @@ -1314,10 +1258,11 @@ void XdsLb::UpdateLocked(UpdateArgs args) { // have been created from a serverlist. // TODO(vpowar): Handle the fallback_address changes when we add support for // fallback in xDS. - if (child_policy_ != nullptr) CreateOrUpdateChildPolicyLocked(); + locality_map_.UpdateLocked(locality_serverlist_, child_policy_config_.get(), + args_, this); // If this is the initial update, start the fallback timer. if (is_initial_update) { - if (lb_fallback_timeout_ms_ > 0 && serverlist_ == nullptr && + if (lb_fallback_timeout_ms_ > 0 && locality_serverlist_.empty() && !fallback_timer_callback_pending_) { grpc_millis deadline = ExecCtx::Get()->Now() + lb_fallback_timeout_ms_; Ref(DEBUG_LOCATION, "on_fallback_timer").release(); // Held by closure @@ -1341,8 +1286,8 @@ void XdsLb::OnFallbackTimerLocked(void* arg, grpc_error* error) { xdslb_policy->fallback_timer_callback_pending_ = false; // If we receive a serverlist after the timer fires but before this callback // actually runs, don't fall back. - if (xdslb_policy->serverlist_ == nullptr && !xdslb_policy->shutting_down_ && - error == GRPC_ERROR_NONE) { + if (xdslb_policy->locality_serverlist_.empty() && + !xdslb_policy->shutting_down_ && error == GRPC_ERROR_NONE) { if (grpc_lb_xds_trace.enabled()) { gpr_log(GPR_INFO, "[xdslb %p] Fallback timer fired. Not using fallback backends", @@ -1352,11 +1297,70 @@ void XdsLb::OnFallbackTimerLocked(void* arg, grpc_error* error) { xdslb_policy->Unref(DEBUG_LOCATION, "on_fallback_timer"); } -// -// code for interacting with the child policy -// +void XdsLb::LocalityMap::PruneLocalities(const LocalityList& locality_list) { + for (auto iter = map_.begin(); iter != map_.end();) { + bool found = false; + for (size_t i = 0; i < locality_list.size(); i++) { + if (!gpr_stricmp(locality_list[i]->locality_name, iter->first.get())) { + found = true; + } + } + if (!found) { // Remove entries not present in the locality list + MutexLock lock(&child_refs_mu_); + iter = map_.erase(iter); + } else + iter++; + } +} + +void XdsLb::LocalityMap::UpdateLocked( + const LocalityList& locality_serverlist, + LoadBalancingPolicy::Config* child_policy_config, + const grpc_channel_args* args, XdsLb* parent) { + if (parent->shutting_down_) return; + for (size_t i = 0; i < locality_serverlist.size(); i++) { + UniquePtr locality_name( + gpr_strdup(locality_serverlist[i]->locality_name)); + auto iter = map_.find(locality_name); + if (iter == map_.end()) { + OrphanablePtr new_entry = + MakeOrphanable(parent->Ref()); + MutexLock lock(&child_refs_mu_); + iter = map_.emplace(std::move(locality_name), std::move(new_entry)).first; + } + // Don't create new child policies if not directed to + xds_grpclb_serverlist* serverlist = + parent->locality_serverlist_[i]->serverlist; + iter->second->UpdateLocked(serverlist, child_policy_config, args); + } + PruneLocalities(locality_serverlist); +} + +void grpc_core::XdsLb::LocalityMap::ShutdownLocked() { + MutexLock lock(&child_refs_mu_); + map_.clear(); +} + +void grpc_core::XdsLb::LocalityMap::ResetBackoffLocked() { + for (auto iter = map_.begin(); iter != map_.end(); iter++) { + iter->second->ResetBackoffLocked(); + } +} + +void grpc_core::XdsLb::LocalityMap::FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) { + MutexLock lock(&child_refs_mu_); + for (auto iter = map_.begin(); iter != map_.end(); iter++) { + iter->second->FillChildRefsForChannelz(child_subchannels, child_channels); + } +} -grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() { +// Locality Entry child policy methods + +grpc_channel_args* +XdsLb::LocalityMap::LocalityEntry::CreateChildPolicyArgsLocked( + const grpc_channel_args* args_in) { const grpc_arg args_to_add[] = { // A channel arg indicating if the target is a backend inferred from a // grpclb load balancer. @@ -1368,15 +1372,16 @@ grpc_channel_args* XdsLb::CreateChildPolicyArgsLocked() { grpc_channel_arg_integer_create( const_cast(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1), }; - return grpc_channel_args_copy_and_add(args_, args_to_add, + return grpc_channel_args_copy_and_add(args_in, args_to_add, GPR_ARRAY_SIZE(args_to_add)); } -OrphanablePtr XdsLb::CreateChildPolicyLocked( +OrphanablePtr +XdsLb::LocalityMap::LocalityEntry::CreateChildPolicyLocked( const char* name, const grpc_channel_args* args) { - Helper* helper = New(Ref()); + Helper* helper = New(this->Ref()); LoadBalancingPolicy::Args lb_policy_args; - lb_policy_args.combiner = combiner(); + lb_policy_args.combiner = parent_->combiner(); lb_policy_args.args = args; lb_policy_args.channel_control_helper = UniquePtr(helper); @@ -1397,22 +1402,27 @@ OrphanablePtr XdsLb::CreateChildPolicyLocked( // child policy. This will make the child policy progress upon activity on xDS // LB, which in turn is tied to the application's call. grpc_pollset_set_add_pollset_set(lb_policy->interested_parties(), - interested_parties()); + parent_->interested_parties()); return lb_policy; } -void XdsLb::CreateOrUpdateChildPolicyLocked() { - if (shutting_down_) return; +void XdsLb::LocalityMap::LocalityEntry::UpdateLocked( + xds_grpclb_serverlist* serverlist, + LoadBalancingPolicy::Config* child_policy_config, + const grpc_channel_args* args_in) { + if (parent_->shutting_down_) return; // This should never be invoked if we do not have serverlist_, as fallback // mode is disabled for xDS plugin. // TODO(juanlishen): Change this as part of implementing fallback mode. - GPR_ASSERT(serverlist_ != nullptr); - GPR_ASSERT(serverlist_->num_servers > 0); + GPR_ASSERT(serverlist != nullptr); + GPR_ASSERT(serverlist->num_servers > 0); // Construct update args. UpdateArgs update_args; - update_args.addresses = ProcessServerlist(serverlist_); - update_args.config = child_policy_config_; - update_args.args = CreateChildPolicyArgsLocked(); + update_args.addresses = ProcessServerlist(serverlist); + update_args.config = + child_policy_config == nullptr ? nullptr : child_policy_config->Ref(); + update_args.args = CreateChildPolicyArgsLocked(args_in); + // If the child policy name changes, we need to create a new child // policy. When this happens, we leave child_policy_ as-is and store // the new child policy in pending_child_policy_. Once the new child @@ -1464,9 +1474,9 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() { // when the new child transitions into state READY. // TODO(juanlishen): If the child policy is not configured via service config, // use whatever algorithm is specified by the balancer. - const char* child_policy_name = child_policy_config_ == nullptr + const char* child_policy_name = child_policy_config == nullptr ? "round_robin" - : child_policy_config_->name(); + : child_policy_config->name(); const bool create_policy = // case 1 child_policy_ == nullptr || @@ -1512,6 +1522,145 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() { policy_to_update->UpdateLocked(std::move(update_args)); } +void XdsLb::LocalityMap::LocalityEntry::ShutdownLocked() { + // Remove the child policy's interested_parties pollset_set from the + // xDS policy. + grpc_pollset_set_del_pollset_set(child_policy_->interested_parties(), + parent_->interested_parties()); + if (pending_child_policy_ != nullptr) { + grpc_pollset_set_del_pollset_set( + pending_child_policy_->interested_parties(), + parent_->interested_parties()); + } + { + MutexLock lock(&child_policy_mu_); + child_policy_.reset(); + pending_child_policy_.reset(); + } +} + +void XdsLb::LocalityMap::LocalityEntry::ResetBackoffLocked() { + child_policy_->ResetBackoffLocked(); + if (pending_child_policy_ != nullptr) { + pending_child_policy_->ResetBackoffLocked(); + } +} + +void XdsLb::LocalityMap::LocalityEntry::FillChildRefsForChannelz( + channelz::ChildRefsList* child_subchannels, + channelz::ChildRefsList* child_channels) { + MutexLock lock(&child_policy_mu_); + child_policy_->FillChildRefsForChannelz(child_subchannels, child_channels); + if (pending_child_policy_ != nullptr) { + pending_child_policy_->FillChildRefsForChannelz(child_subchannels, + child_channels); + } +} + +void XdsLb::LocalityMap::LocalityEntry::Orphan() { + ShutdownLocked(); + Unref(); +} + +// +// LocalityEntry::Helper implementation +// +bool XdsLb::LocalityMap::LocalityEntry::Helper::CalledByPendingChild() const { + GPR_ASSERT(child_ != nullptr); + return child_ == entry_->pending_child_policy_.get(); +} + +bool XdsLb::LocalityMap::LocalityEntry::Helper::CalledByCurrentChild() const { + GPR_ASSERT(child_ != nullptr); + return child_ == entry_->child_policy_.get(); +} + +Subchannel* XdsLb::LocalityMap::LocalityEntry::Helper::CreateSubchannel( + const grpc_channel_args& args) { + if (entry_->parent_->shutting_down_ || + (!CalledByPendingChild() && !CalledByCurrentChild())) { + return nullptr; + } + return entry_->parent_->channel_control_helper()->CreateSubchannel(args); +} + +grpc_channel* XdsLb::LocalityMap::LocalityEntry::Helper::CreateChannel( + const char* target, const grpc_channel_args& args) { + if (entry_->parent_->shutting_down_ || + (!CalledByPendingChild() && !CalledByCurrentChild())) { + return nullptr; + } + return entry_->parent_->channel_control_helper()->CreateChannel(target, args); +} + +void XdsLb::LocalityMap::LocalityEntry::Helper::UpdateState( + grpc_connectivity_state state, grpc_error* state_error, + UniquePtr picker) { + if (entry_->parent_->shutting_down_) { + GRPC_ERROR_UNREF(state_error); + return; + } + // If this request is from the pending child policy, ignore it until + // it reports READY, at which point we swap it into place. + if (CalledByPendingChild()) { + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p helper %p] pending child policy %p reports state=%s", + entry_->parent_.get(), this, entry_->pending_child_policy_.get(), + grpc_connectivity_state_name(state)); + } + if (state != GRPC_CHANNEL_READY) { + GRPC_ERROR_UNREF(state_error); + return; + } + grpc_pollset_set_del_pollset_set( + entry_->child_policy_->interested_parties(), + entry_->parent_->interested_parties()); + MutexLock lock(&entry_->child_policy_mu_); + entry_->child_policy_ = std::move(entry_->pending_child_policy_); + } else if (!CalledByCurrentChild()) { + // This request is from an outdated child, so ignore it. + GRPC_ERROR_UNREF(state_error); + return; + } + // TODO(juanlishen): When in fallback mode, pass the child picker + // through without wrapping it. (Or maybe use a different helper for + // the fallback policy?) + GPR_ASSERT(entry_->parent_->lb_chand_ != nullptr); + RefCountedPtr client_stats = + entry_->parent_->lb_chand_->lb_calld() == nullptr + ? nullptr + : entry_->parent_->lb_chand_->lb_calld()->client_stats(); + entry_->parent_->channel_control_helper()->UpdateState( + state, state_error, + UniquePtr( + New(std::move(picker), std::move(client_stats)))); +} + +void XdsLb::LocalityMap::LocalityEntry::Helper::RequestReresolution() { + if (entry_->parent_->shutting_down_) return; + // If there is a pending child policy, ignore re-resolution requests + // from the current child policy (or any outdated child). + if (entry_->pending_child_policy_ != nullptr && !CalledByPendingChild()) { + return; + } + if (grpc_lb_xds_trace.enabled()) { + gpr_log(GPR_INFO, + "[xdslb %p] Re-resolution requested from the internal RR policy " + "(%p).", + entry_->parent_.get(), entry_->child_policy_.get()); + } + GPR_ASSERT(entry_->parent_->lb_chand_ != nullptr); + // If we are talking to a balancer, we expect to get updated addresses + // from the balancer, so we can ignore the re-resolution request from + // the child policy. Otherwise, pass the re-resolution request up to the + // channel. + if (entry_->parent_->lb_chand_->lb_calld() == nullptr || + !entry_->parent_->lb_chand_->lb_calld()->seen_initial_response()) { + entry_->parent_->channel_control_helper()->RequestReresolution(); + } +} + // // factory // diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 7de1c221a13..6994f63bee4 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -43,6 +43,7 @@ #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/gethostname.h" +#include "src/core/lib/iomgr/iomgr_custom.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/json/json.h" @@ -308,7 +309,11 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) { if (service_config_string != nullptr) { GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", r, service_config_string); - result.service_config = ServiceConfig::Create(service_config_string); + grpc_error* service_config_error = GRPC_ERROR_NONE; + result.service_config = + ServiceConfig::Create(service_config_string, &service_config_error); + // Error is currently unused. + GRPC_ERROR_UNREF(service_config_error); } gpr_free(service_config_string); } @@ -426,8 +431,11 @@ static grpc_address_resolver_vtable ares_resolver = { grpc_resolve_address_ares, blocking_resolve_address_ares}; static bool should_use_ares(const char* resolver_env) { - return resolver_env == nullptr || strlen(resolver_env) == 0 || - gpr_stricmp(resolver_env, "ares") == 0; + // TODO(lidiz): Remove the "g_custom_iomgr_enabled" flag once c-ares support + // custom IO managers (e.g. gevent). + return !g_custom_iomgr_enabled && + (resolver_env == nullptr || strlen(resolver_env) == 0 || + gpr_stricmp(resolver_env, "ares") == 0); } void grpc_resolver_dns_ares_init() { diff --git a/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/src/core/ext/filters/client_channel/resolver_result_parsing.cc index daac4f0ff6a..7148e16e70b 100644 --- a/src/core/ext/filters/client_channel/resolver_result_parsing.cc +++ b/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -52,7 +52,10 @@ ProcessedResolverResult::ProcessedResolverResult( const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(resolver_result->args, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { - service_config_ = ServiceConfig::Create(service_config_json); + grpc_error* error = GRPC_ERROR_NONE; + service_config_ = ServiceConfig::Create(service_config_json, &error); + // Error is currently unused. + GRPC_ERROR_UNREF(error); } } else { // Add the service config JSON to channel args so that it's diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index bbf671d979e..d9e64ccf5a8 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -33,23 +33,201 @@ namespace grpc_core { -RefCountedPtr ServiceConfig::Create(const char* json) { +namespace { +typedef InlinedVector, + ServiceConfig::kNumPreallocatedParsers> + ServiceConfigParserList; +ServiceConfigParserList* registered_parsers; + +// Consumes all the errors in the vector and forms a referencing error from +// them. If the vector is empty, return GRPC_ERROR_NONE. +template +grpc_error* CreateErrorFromVector(const char* desc, + InlinedVector* error_list) { + grpc_error* error = GRPC_ERROR_NONE; + if (error_list->size() != 0) { + error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + desc, error_list->data(), error_list->size()); + // Remove refs to all errors in error_list. + for (size_t i = 0; i < error_list->size(); i++) { + GRPC_ERROR_UNREF((*error_list)[i]); + } + error_list->clear(); + } + return error; +} +} // namespace + +RefCountedPtr ServiceConfig::Create(const char* json, + grpc_error** error) { UniquePtr service_config_json(gpr_strdup(json)); UniquePtr json_string(gpr_strdup(json)); + GPR_DEBUG_ASSERT(error != nullptr); grpc_json* json_tree = grpc_json_parse_string(json_string.get()); if (json_tree == nullptr) { - gpr_log(GPR_INFO, "failed to parse JSON for service config"); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "failed to parse JSON for service config"); return nullptr; } - return MakeRefCounted(std::move(service_config_json), - std::move(json_string), json_tree); + return MakeRefCounted( + std::move(service_config_json), std::move(json_string), json_tree, error); } ServiceConfig::ServiceConfig(UniquePtr service_config_json, - UniquePtr json_string, grpc_json* json_tree) + UniquePtr json_string, grpc_json* json_tree, + grpc_error** error) : service_config_json_(std::move(service_config_json)), json_string_(std::move(json_string)), - json_tree_(json_tree) {} + json_tree_(json_tree) { + GPR_DEBUG_ASSERT(error != nullptr); + if (json_tree->type != GRPC_JSON_OBJECT || json_tree->key != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Malformed service Config JSON object"); + return; + } + grpc_error* error_list[2]; + int error_count = 0; + grpc_error* global_error = ParseGlobalParams(json_tree); + grpc_error* local_error = ParsePerMethodParams(json_tree); + if (global_error != GRPC_ERROR_NONE) { + error_list[error_count++] = global_error; + } + if (local_error != GRPC_ERROR_NONE) { + error_list[error_count++] = local_error; + } + if (error_count > 0) { + *error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Service config parsing error", error_list, error_count); + GRPC_ERROR_UNREF(global_error); + GRPC_ERROR_UNREF(local_error); + } +} + +grpc_error* ServiceConfig::ParseGlobalParams(const grpc_json* json_tree) { + GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); + GPR_DEBUG_ASSERT(json_tree_->key == nullptr); + InlinedVector error_list; + for (size_t i = 0; i < registered_parsers->size(); i++) { + grpc_error* parser_error = GRPC_ERROR_NONE; + auto parsed_obj = + (*registered_parsers)[i]->ParseGlobalParams(json_tree, &parser_error); + if (parser_error != GRPC_ERROR_NONE) { + error_list.push_back(parser_error); + } + parsed_global_service_config_objects_.push_back(std::move(parsed_obj)); + } + return CreateErrorFromVector("Global Params", &error_list); +} + +grpc_error* ServiceConfig::ParseJsonMethodConfigToServiceConfigObjectsTable( + const grpc_json* json, + SliceHashTable::Entry* entries, + size_t* idx) { + auto objs_vector = MakeUnique(); + InlinedVector error_list; + for (size_t i = 0; i < registered_parsers->size(); i++) { + grpc_error* parser_error = GRPC_ERROR_NONE; + auto parsed_obj = + (*registered_parsers)[i]->ParsePerMethodParams(json, &parser_error); + if (parser_error != GRPC_ERROR_NONE) { + error_list.push_back(parser_error); + } + objs_vector->push_back(std::move(parsed_obj)); + } + const auto* vector_ptr = objs_vector.get(); + service_config_objects_vectors_storage_.push_back(std::move(objs_vector)); + // Construct list of paths. + InlinedVector, 10> paths; + for (grpc_json* child = json->child; child != nullptr; child = child->next) { + if (child->key == nullptr) continue; + if (strcmp(child->key, "name") == 0) { + if (child->type != GRPC_JSON_ARRAY) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:not of type Array")); + goto wrap_error; + } + for (grpc_json* name = child->child; name != nullptr; name = name->next) { + grpc_error* parse_error = GRPC_ERROR_NONE; + UniquePtr path = ParseJsonMethodName(name, &parse_error); + if (path == nullptr) { + error_list.push_back(parse_error); + } else { + GPR_DEBUG_ASSERT(parse_error == GRPC_ERROR_NONE); + paths.push_back(std::move(path)); + } + } + } + } + if (paths.size() == 0) { + error_list.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No names specified")); + } + // Add entry for each path. + for (size_t i = 0; i < paths.size(); ++i) { + entries[*idx].key = grpc_slice_from_copied_string(paths[i].get()); + entries[*idx].value = vector_ptr; + ++*idx; + } +wrap_error: + return CreateErrorFromVector("methodConfig", &error_list); +} + +grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_json* json_tree) { + GPR_DEBUG_ASSERT(json_tree_->type == GRPC_JSON_OBJECT); + GPR_DEBUG_ASSERT(json_tree_->key == nullptr); + SliceHashTable::Entry* entries = nullptr; + size_t num_entries = 0; + InlinedVector error_list; + for (grpc_json* field = json_tree->child; field != nullptr; + field = field->next) { + if (field->key == nullptr) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "error:Illegal key value - NULL")); + continue; + } + if (strcmp(field->key, "methodConfig") == 0) { + if (entries != nullptr) { + GPR_ASSERT(false); + } + if (field->type != GRPC_JSON_ARRAY) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:methodConfig error:not of type Array")); + } + for (grpc_json* method = field->child; method != nullptr; + method = method->next) { + int count = CountNamesInMethodConfig(method); + if (count <= 0) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:methodConfig error:No names found")); + } + num_entries += static_cast(count); + } + entries = static_cast< + SliceHashTable::Entry*>(gpr_zalloc( + num_entries * + sizeof(SliceHashTable::Entry))); + size_t idx = 0; + for (grpc_json* method = field->child; method != nullptr; + method = method->next) { + grpc_error* error = ParseJsonMethodConfigToServiceConfigObjectsTable( + method, entries, &idx); + if (error != GRPC_ERROR_NONE) { + error_list.push_back(error); + } + } + // idx might not be equal to num_entries due to parsing errors + num_entries = idx; + break; + } + } + if (entries != nullptr) { + parsed_method_service_config_objects_table_ = + SliceHashTable::Create( + num_entries, entries, nullptr); + gpr_free(entries); + } + return CreateErrorFromVector("Method Params", &error_list); +} ServiceConfig::~ServiceConfig() { grpc_json_destroy(json_tree_); } @@ -84,28 +262,99 @@ int ServiceConfig::CountNamesInMethodConfig(grpc_json* json) { return num_names; } -UniquePtr ServiceConfig::ParseJsonMethodName(grpc_json* json) { - if (json->type != GRPC_JSON_OBJECT) return nullptr; +UniquePtr ServiceConfig::ParseJsonMethodName(grpc_json* json, + grpc_error** error) { + if (json->type != GRPC_JSON_OBJECT) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:type is not object"); + return nullptr; + } const char* service_name = nullptr; const char* method_name = nullptr; for (grpc_json* child = json->child; child != nullptr; child = child->next) { - if (child->key == nullptr) return nullptr; - if (child->type != GRPC_JSON_STRING) return nullptr; + if (child->key == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:Child entry with no key"); + return nullptr; + } + if (child->type != GRPC_JSON_STRING) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error:Child entry not of type string"); + return nullptr; + } if (strcmp(child->key, "service") == 0) { - if (service_name != nullptr) return nullptr; // Duplicate. - if (child->value == nullptr) return nullptr; + if (service_name != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error: field:service error:Multiple entries"); + return nullptr; // Duplicate. + } + if (child->value == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error: field:service error:empty value"); + return nullptr; + } service_name = child->value; } else if (strcmp(child->key, "method") == 0) { - if (method_name != nullptr) return nullptr; // Duplicate. - if (child->value == nullptr) return nullptr; + if (method_name != nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error: field:method error:multiple entries"); + return nullptr; // Duplicate. + } + if (child->value == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error: field:method error:empty value"); + return nullptr; + } method_name = child->value; } } - if (service_name == nullptr) return nullptr; // Required field. + if (service_name == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:name error: field:service error:not found"); + return nullptr; // Required field. + } char* path; gpr_asprintf(&path, "/%s/%s", service_name, method_name == nullptr ? "*" : method_name); return UniquePtr(path); } +const ServiceConfig::ServiceConfigObjectsVector* const* +ServiceConfig::GetMethodServiceConfigObjectsVector(const grpc_slice& path) { + const auto* value = parsed_method_service_config_objects_table_->Get(path); + // If we didn't find a match for the path, try looking for a wildcard + // entry (i.e., change "/service/method" to "/service/*"). + if (value == nullptr) { + char* path_str = grpc_slice_to_c_string(path); + const char* sep = strrchr(path_str, '/') + 1; + const size_t len = (size_t)(sep - path_str); + char* buf = (char*)gpr_malloc(len + 2); // '*' and NUL + memcpy(buf, path_str, len); + buf[len] = '*'; + buf[len + 1] = '\0'; + grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); + gpr_free(buf); + value = parsed_method_service_config_objects_table_->Get(wildcard_path); + grpc_slice_unref_internal(wildcard_path); + gpr_free(path_str); + if (value == nullptr) return nullptr; + } + return value; +} + +size_t ServiceConfig::RegisterParser(UniquePtr parser) { + registered_parsers->push_back(std::move(parser)); + return registered_parsers->size() - 1; +} + +void ServiceConfig::Init() { + GPR_ASSERT(registered_parsers == nullptr); + registered_parsers = New(); +} + +void ServiceConfig::Shutdown() { + Delete(registered_parsers); + registered_parsers = nullptr; +} + } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index d9063479e32..0f2d2b387ae 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -25,6 +25,7 @@ #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/iomgr/error.h" #include "src/core/lib/json/json.h" #include "src/core/lib/slice/slice_hash_table.h" @@ -54,11 +55,46 @@ namespace grpc_core { +/// This is the base class that all service config parsers MUST use to store +/// parsed service config data. +class ServiceConfigParsedObject { + public: + virtual ~ServiceConfigParsedObject() = default; + + GRPC_ABSTRACT_BASE_CLASS; +}; + +/// This is the base class that all service config parsers should derive from. +class ServiceConfigParser { + public: + virtual ~ServiceConfigParser() = default; + + virtual UniquePtr ParseGlobalParams( + const grpc_json* json, grpc_error** error) { + GPR_DEBUG_ASSERT(error != nullptr); + return nullptr; + } + + virtual UniquePtr ParsePerMethodParams( + const grpc_json* json, grpc_error** error) { + GPR_DEBUG_ASSERT(error != nullptr); + return nullptr; + } + + GRPC_ABSTRACT_BASE_CLASS; +}; + class ServiceConfig : public RefCounted { public: + static constexpr int kNumPreallocatedParsers = 4; + typedef InlinedVector, + kNumPreallocatedParsers> + ServiceConfigObjectsVector; + /// Creates a new service config from parsing \a json_string. /// Returns null on parse error. - static RefCountedPtr Create(const char* json); + static RefCountedPtr Create(const char* json, + grpc_error** error); ~ServiceConfig(); @@ -96,6 +132,30 @@ class ServiceConfig : public RefCounted { static RefCountedPtr MethodConfigTableLookup( const SliceHashTable>& table, const grpc_slice& path); + /// Retrieves the parsed global service config object at index \a index. + ServiceConfigParsedObject* GetParsedGlobalServiceConfigObject(int index) { + GPR_DEBUG_ASSERT( + index < static_cast(parsed_global_service_config_objects_.size())); + return parsed_global_service_config_objects_[index].get(); + } + + /// Retrieves the vector of method service config objects for a given path \a + /// path. + const ServiceConfigObjectsVector* const* GetMethodServiceConfigObjectsVector( + const grpc_slice& path); + + /// Globally register a service config parser. On successful registration, it + /// returns the index at which the parser was registered. On failure, -1 is + /// returned. Each new service config update will go through all the + /// registered parser. Each parser is responsible for reading the service + /// config json and returning a parsed object. This parsed object can later be + /// retrieved using the same index that was returned at registration time. + static size_t RegisterParser(UniquePtr parser); + + static void Init(); + + static void Shutdown(); + private: // So New() can call our private ctor. template @@ -103,14 +163,20 @@ class ServiceConfig : public RefCounted { // Takes ownership of \a json_tree. ServiceConfig(UniquePtr service_config_json, - UniquePtr json_string, grpc_json* json_tree); + UniquePtr json_string, grpc_json* json_tree, + grpc_error** error); + + // Helper functions to parse the service config + grpc_error* ParseGlobalParams(const grpc_json* json_tree); + grpc_error* ParsePerMethodParams(const grpc_json* json_tree); // Returns the number of names specified in the method config \a json. static int CountNamesInMethodConfig(grpc_json* json); // Returns a path string for the JSON name object specified by \a json. - // Returns null on error. - static UniquePtr ParseJsonMethodName(grpc_json* json); + // Returns null on error, and stores error in \a error. + static UniquePtr ParseJsonMethodName(grpc_json* json, + grpc_error** error); // Parses the method config from \a json. Adds an entry to \a entries for // each name found, incrementing \a idx for each entry added. @@ -120,9 +186,26 @@ class ServiceConfig : public RefCounted { grpc_json* json, CreateValue create_value, typename SliceHashTable>::Entry* entries, size_t* idx); + grpc_error* ParseJsonMethodConfigToServiceConfigObjectsTable( + const grpc_json* json, + SliceHashTable::Entry* entries, + size_t* idx); + UniquePtr service_config_json_; UniquePtr json_string_; // Underlying storage for json_tree. grpc_json* json_tree_; + + InlinedVector, kNumPreallocatedParsers> + parsed_global_service_config_objects_; + // A map from the method name to the service config objects vector. Note that + // we are using a raw pointer and not a unique pointer so that we can use the + // same vector for multiple names. + RefCountedPtr> + parsed_method_service_config_objects_table_; + // Storage for all the vectors that are being used in + // parsed_method_service_config_objects_table_. + InlinedVector, 32> + service_config_objects_vectors_storage_; }; // @@ -157,7 +240,10 @@ bool ServiceConfig::ParseJsonMethodConfig( if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) return false; for (grpc_json* name = child->child; name != nullptr; name = name->next) { - UniquePtr path = ParseJsonMethodName(name); + grpc_error* error = GRPC_ERROR_NONE; + UniquePtr path = ParseJsonMethodName(name, &error); + // We are not reporting the error here. + GRPC_ERROR_UNREF(error); if (path == nullptr) return false; paths.push_back(std::move(path)); } diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index 8bb0c4c3498..20a6023f71c 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -590,8 +590,11 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, const char* service_config_json = grpc_channel_arg_get_string( grpc_channel_args_find(args_, GRPC_ARG_SERVICE_CONFIG)); if (service_config_json != nullptr) { + grpc_error* service_config_error = GRPC_ERROR_NONE; RefCountedPtr service_config = - ServiceConfig::Create(service_config_json); + ServiceConfig::Create(service_config_json, &service_config_error); + // service_config_error is currently unused. + GRPC_ERROR_UNREF(service_config_error); if (service_config != nullptr) { HealthCheckParams params; service_config->ParseGlobalParams(HealthCheckParams::Parse, ¶ms); diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index 8a422ddca54..4d120c0eb76 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -319,8 +319,11 @@ static grpc_error* init_channel_elem(grpc_channel_element* elem, grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG); const char* service_config_str = grpc_channel_arg_get_string(channel_arg); if (service_config_str != nullptr) { + grpc_error* service_config_error = GRPC_ERROR_NONE; grpc_core::RefCountedPtr service_config = - grpc_core::ServiceConfig::Create(service_config_str); + grpc_core::ServiceConfig::Create(service_config_str, + &service_config_error); + GRPC_ERROR_UNREF(service_config_error); if (service_config != nullptr) { chand->method_limit_table = service_config->CreateMethodConfigTable( grpc_core::MessageSizeLimits::CreateFromJson); diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 404539c9e13..fe92835f690 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -645,17 +645,22 @@ void grpc_chttp2_stream_unref(grpc_chttp2_stream* s) { } #endif -grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t, - grpc_stream_refcount* refcount, - const void* server_data, - gpr_arena* arena) - : t(t), refcount(refcount), metadata_buffer{{arena}, {arena}} { +grpc_chttp2_stream::Reffer::Reffer(grpc_chttp2_stream* s) { /* We reserve one 'active stream' that's dropped when the stream is read-closed. The others are for Chttp2IncomingByteStreams that are actively reading */ - GRPC_CHTTP2_STREAM_REF(this, "chttp2"); - GRPC_CHTTP2_REF_TRANSPORT(t, "stream"); + GRPC_CHTTP2_STREAM_REF(s, "chttp2"); + GRPC_CHTTP2_REF_TRANSPORT(s->t, "stream"); +} +grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t, + grpc_stream_refcount* refcount, + const void* server_data, + gpr_arena* arena) + : t(t), + refcount(refcount), + reffer(this), + metadata_buffer{{arena}, {arena}} { if (server_data) { id = static_cast((uintptr_t)server_data); *t->accepting_stream = this; @@ -2598,6 +2603,9 @@ static void start_bdp_ping_locked(void* tp, grpc_error* error) { gpr_log(GPR_INFO, "%s: Start BDP ping err=%s", t->peer_string, grpc_error_string(error)); } + if (error != GRPC_ERROR_NONE || t->closed_with_error != GRPC_ERROR_NONE) { + return; + } /* Reset the keepalive ping timer */ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) { grpc_timer_cancel(&t->keepalive_ping_timer); @@ -2611,7 +2619,7 @@ static void finish_bdp_ping_locked(void* tp, grpc_error* error) { gpr_log(GPR_INFO, "%s: Complete BDP ping err=%s", t->peer_string, grpc_error_string(error)); } - if (error != GRPC_ERROR_NONE) { + if (error != GRPC_ERROR_NONE || t->closed_with_error != GRPC_ERROR_NONE) { GRPC_CHTTP2_UNREF_TRANSPORT(t, "bdp_ping"); return; } diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 760324c0c95..e4fd5928f2c 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -510,6 +510,12 @@ struct grpc_chttp2_stream { void* context; grpc_chttp2_transport* t; grpc_stream_refcount* refcount; + // Reffer is a 0-len structure, simply reffing `t` and `refcount` in its ctor + // before initializing the rest of the stream, to avoid cache misses. This + // field MUST be right after `t` and `refcount`. + struct Reffer { + explicit Reffer(grpc_chttp2_stream* s); + } reffer; grpc_closure destroy_stream; grpc_closure* destroy_stream_arg; diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 9551b4ba496..76a32dc4049 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -177,7 +177,7 @@ struct op_and_state { bool done = false; struct stream_obj* s; /* Pointer back to the stream object */ /* next op_and_state in the linked list */ - struct op_and_state* next; + struct op_and_state* next = nullptr; }; struct op_storage { @@ -324,7 +324,7 @@ static grpc_error* make_error_with_desc(int error_code, const char* desc) { inline op_and_state::op_and_state(stream_obj* s, const grpc_transport_stream_op_batch& op) - : op(op), state(s->arena), s(s), next(s->storage.head) {} + : op(op), state(s->arena), s(s) {} /* Add a new stream op to op storage. @@ -335,10 +335,8 @@ static void add_to_storage(struct stream_obj* s, /* add new op at the beginning of the linked list. The memory is freed in remove_from_storage */ op_and_state* new_op = grpc_core::New(s, *op); - // Pontential fix to crash on GPR_ASSERT(!curr->done) - // TODO (mxyan): check if this is indeed necessary. - new_op->done = false; gpr_mu_lock(&s->mu); + new_op->next = storage->head; storage->head = new_op; storage->num_pending_ops++; if (op->send_message) { diff --git a/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c new file mode 100644 index 00000000000..2af77c59efb --- /dev/null +++ b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.c @@ -0,0 +1,105 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/api/v2/endpoint/load_report.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/api/v2/endpoint/load_report.upb.h" +#include "envoy/api/v2/core/address.upb.h" +#include "envoy/api/v2/core/base.upb.h" +#include "google/protobuf/duration.upb.h" +#include "validate/validate.upb.h" +#include "gogoproto/gogo.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_api_v2_endpoint_UpstreamLocalityStats_submsgs[3] = { + &envoy_api_v2_core_Locality_msginit, + &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, + &envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_UpstreamLocalityStats__fields[7] = { + {1, UPB_SIZE(28, 32), 0, 0, 11, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {3, UPB_SIZE(8, 8), 0, 0, 4, 1}, + {4, UPB_SIZE(16, 16), 0, 0, 4, 1}, + {5, UPB_SIZE(32, 40), 0, 1, 11, 3}, + {6, UPB_SIZE(24, 24), 0, 0, 13, 1}, + {7, UPB_SIZE(36, 48), 0, 2, 11, 3}, +}; + +const upb_msglayout envoy_api_v2_endpoint_UpstreamLocalityStats_msginit = { + &envoy_api_v2_endpoint_UpstreamLocalityStats_submsgs[0], + &envoy_api_v2_endpoint_UpstreamLocalityStats__fields[0], + UPB_SIZE(40, 56), 7, false, +}; + +static const upb_msglayout *const envoy_api_v2_endpoint_UpstreamEndpointStats_submsgs[2] = { + &envoy_api_v2_core_Address_msginit, + &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_UpstreamEndpointStats__fields[5] = { + {1, UPB_SIZE(24, 24), 0, 0, 11, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {3, UPB_SIZE(8, 8), 0, 0, 4, 1}, + {4, UPB_SIZE(16, 16), 0, 0, 4, 1}, + {5, UPB_SIZE(28, 32), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_api_v2_endpoint_UpstreamEndpointStats_msginit = { + &envoy_api_v2_endpoint_UpstreamEndpointStats_submsgs[0], + &envoy_api_v2_endpoint_UpstreamEndpointStats__fields[0], + UPB_SIZE(32, 40), 5, false, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_EndpointLoadMetricStats__fields[3] = { + {1, UPB_SIZE(16, 16), 0, 0, 9, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {3, UPB_SIZE(8, 8), 0, 0, 1, 1}, +}; + +const upb_msglayout envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit = { + NULL, + &envoy_api_v2_endpoint_EndpointLoadMetricStats__fields[0], + UPB_SIZE(24, 32), 3, false, +}; + +static const upb_msglayout *const envoy_api_v2_endpoint_ClusterStats_submsgs[3] = { + &envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, + &envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_ClusterStats__fields[5] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(20, 32), 0, 1, 11, 3}, + {3, UPB_SIZE(0, 0), 0, 0, 4, 1}, + {4, UPB_SIZE(16, 24), 0, 2, 11, 1}, + {5, UPB_SIZE(24, 40), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_api_v2_endpoint_ClusterStats_msginit = { + &envoy_api_v2_endpoint_ClusterStats_submsgs[0], + &envoy_api_v2_endpoint_ClusterStats__fields[0], + UPB_SIZE(32, 48), 5, false, +}; + +static const upb_msglayout_field envoy_api_v2_endpoint_ClusterStats_DroppedRequests__fields[2] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 4, 1}, +}; + +const upb_msglayout envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit = { + NULL, + &envoy_api_v2_endpoint_ClusterStats_DroppedRequests__fields[0], + UPB_SIZE(16, 32), 2, false, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h new file mode 100644 index 00000000000..7ee2129f436 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/api/v2/endpoint/load_report.upb.h @@ -0,0 +1,299 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/api/v2/endpoint/load_report.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_API_V2_ENDPOINT_LOAD_REPORT_PROTO_UPB_H_ +#define ENVOY_API_V2_ENDPOINT_LOAD_REPORT_PROTO_UPB_H_ + +#include "upb/generated_util.h" + +#include "upb/msg.h" + +#include "upb/decode.h" +#include "upb/encode.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_api_v2_endpoint_UpstreamLocalityStats; +struct envoy_api_v2_endpoint_UpstreamEndpointStats; +struct envoy_api_v2_endpoint_EndpointLoadMetricStats; +struct envoy_api_v2_endpoint_ClusterStats; +struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests; +typedef struct envoy_api_v2_endpoint_UpstreamLocalityStats envoy_api_v2_endpoint_UpstreamLocalityStats; +typedef struct envoy_api_v2_endpoint_UpstreamEndpointStats envoy_api_v2_endpoint_UpstreamEndpointStats; +typedef struct envoy_api_v2_endpoint_EndpointLoadMetricStats envoy_api_v2_endpoint_EndpointLoadMetricStats; +typedef struct envoy_api_v2_endpoint_ClusterStats envoy_api_v2_endpoint_ClusterStats; +typedef struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests envoy_api_v2_endpoint_ClusterStats_DroppedRequests; +extern const upb_msglayout envoy_api_v2_endpoint_UpstreamLocalityStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_UpstreamEndpointStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_ClusterStats_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit; +struct envoy_api_v2_core_Address; +struct envoy_api_v2_core_Locality; +struct google_protobuf_Duration; +extern const upb_msglayout envoy_api_v2_core_Address_msginit; +extern const upb_msglayout envoy_api_v2_core_Locality_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; + +/* Enums */ + + +/* envoy.api.v2.endpoint.UpstreamLocalityStats */ + +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats *envoy_api_v2_endpoint_UpstreamLocalityStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamLocalityStats *)upb_msg_new(&envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats *envoy_api_v2_endpoint_UpstreamLocalityStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_UpstreamLocalityStats *ret = envoy_api_v2_endpoint_UpstreamLocalityStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_UpstreamLocalityStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_UpstreamLocalityStats_serialize(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, arena, len); +} + +UPB_INLINE const struct envoy_api_v2_core_Locality* envoy_api_v2_endpoint_UpstreamLocalityStats_locality(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Locality*, UPB_SIZE(28, 32)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamLocalityStats_total_successful_requests(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamLocalityStats_total_requests_in_progress(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamLocalityStats_total_error_requests(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)); } +UPB_INLINE const envoy_api_v2_endpoint_EndpointLoadMetricStats* const* envoy_api_v2_endpoint_UpstreamLocalityStats_load_metric_stats(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_EndpointLoadMetricStats* const*)_upb_array_accessor(msg, UPB_SIZE(32, 40), len); } +UPB_INLINE uint32_t envoy_api_v2_endpoint_UpstreamLocalityStats_priority(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg) { return UPB_FIELD_AT(msg, uint32_t, UPB_SIZE(24, 24)); } +UPB_INLINE const envoy_api_v2_endpoint_UpstreamEndpointStats* const* envoy_api_v2_endpoint_UpstreamLocalityStats_upstream_endpoint_stats(const envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_UpstreamEndpointStats* const*)_upb_array_accessor(msg, UPB_SIZE(36, 48), len); } + +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_locality(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, struct envoy_api_v2_core_Locality* value) { + UPB_FIELD_AT(msg, struct envoy_api_v2_core_Locality*, UPB_SIZE(28, 32)) = value; +} +UPB_INLINE struct envoy_api_v2_core_Locality* envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_locality(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena) { + struct envoy_api_v2_core_Locality* sub = (struct envoy_api_v2_core_Locality*)envoy_api_v2_endpoint_UpstreamLocalityStats_locality(msg); + if (sub == NULL) { + sub = (struct envoy_api_v2_core_Locality*)upb_msg_new(&envoy_api_v2_core_Locality_msginit, arena); + if (!sub) return NULL; + envoy_api_v2_endpoint_UpstreamLocalityStats_set_locality(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_successful_requests(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_requests_in_progress(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_error_requests(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_load_metric_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 40), len); +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamLocalityStats_resize_load_metric_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_resize_accessor(msg, UPB_SIZE(32, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_EndpointLoadMetricStats* envoy_api_v2_endpoint_UpstreamLocalityStats_add_load_metric_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_EndpointLoadMetricStats* sub = (struct envoy_api_v2_endpoint_EndpointLoadMetricStats*)upb_msg_new(&envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(32, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamLocalityStats_set_priority(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, uint32_t value) { + UPB_FIELD_AT(msg, uint32_t, UPB_SIZE(24, 24)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats** envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_upstream_endpoint_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_UpstreamEndpointStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 48), len); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats** envoy_api_v2_endpoint_UpstreamLocalityStats_resize_upstream_endpoint_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamEndpointStats**)_upb_array_resize_accessor(msg, UPB_SIZE(36, 48), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_UpstreamEndpointStats* envoy_api_v2_endpoint_UpstreamLocalityStats_add_upstream_endpoint_stats(envoy_api_v2_endpoint_UpstreamLocalityStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_UpstreamEndpointStats* sub = (struct envoy_api_v2_endpoint_UpstreamEndpointStats*)upb_msg_new(&envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(36, 48), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.api.v2.endpoint.UpstreamEndpointStats */ + +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats *envoy_api_v2_endpoint_UpstreamEndpointStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamEndpointStats *)upb_msg_new(&envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamEndpointStats *envoy_api_v2_endpoint_UpstreamEndpointStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_UpstreamEndpointStats *ret = envoy_api_v2_endpoint_UpstreamEndpointStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_UpstreamEndpointStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_UpstreamEndpointStats_serialize(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_UpstreamEndpointStats_msginit, arena, len); +} + +UPB_INLINE const struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_UpstreamEndpointStats_address(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Address*, UPB_SIZE(24, 24)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamEndpointStats_total_successful_requests(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamEndpointStats_total_requests_in_progress(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_UpstreamEndpointStats_total_error_requests(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)); } +UPB_INLINE const envoy_api_v2_endpoint_EndpointLoadMetricStats* const* envoy_api_v2_endpoint_UpstreamEndpointStats_load_metric_stats(const envoy_api_v2_endpoint_UpstreamEndpointStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_EndpointLoadMetricStats* const*)_upb_array_accessor(msg, UPB_SIZE(28, 32), len); } + +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_address(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, struct envoy_api_v2_core_Address* value) { + UPB_FIELD_AT(msg, struct envoy_api_v2_core_Address*, UPB_SIZE(24, 24)) = value; +} +UPB_INLINE struct envoy_api_v2_core_Address* envoy_api_v2_endpoint_UpstreamEndpointStats_mutable_address(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, upb_arena *arena) { + struct envoy_api_v2_core_Address* sub = (struct envoy_api_v2_core_Address*)envoy_api_v2_endpoint_UpstreamEndpointStats_address(msg); + if (sub == NULL) { + sub = (struct envoy_api_v2_core_Address*)upb_msg_new(&envoy_api_v2_core_Address_msginit, arena); + if (!sub) return NULL; + envoy_api_v2_endpoint_UpstreamEndpointStats_set_address(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_total_successful_requests(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_total_requests_in_progress(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_UpstreamEndpointStats_set_total_error_requests(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(16, 16)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamEndpointStats_mutable_load_metric_stats(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 32), len); +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats** envoy_api_v2_endpoint_UpstreamEndpointStats_resize_load_metric_stats(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats**)_upb_array_resize_accessor(msg, UPB_SIZE(28, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_EndpointLoadMetricStats* envoy_api_v2_endpoint_UpstreamEndpointStats_add_load_metric_stats(envoy_api_v2_endpoint_UpstreamEndpointStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_EndpointLoadMetricStats* sub = (struct envoy_api_v2_endpoint_EndpointLoadMetricStats*)upb_msg_new(&envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(28, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.api.v2.endpoint.EndpointLoadMetricStats */ + +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats *envoy_api_v2_endpoint_EndpointLoadMetricStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_EndpointLoadMetricStats *)upb_msg_new(&envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_EndpointLoadMetricStats *envoy_api_v2_endpoint_EndpointLoadMetricStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_EndpointLoadMetricStats *ret = envoy_api_v2_endpoint_EndpointLoadMetricStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_EndpointLoadMetricStats_serialize(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_EndpointLoadMetricStats_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_api_v2_endpoint_EndpointLoadMetricStats_metric_name(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(16, 16)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_EndpointLoadMetricStats_num_requests_finished_with_metric(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE double envoy_api_v2_endpoint_EndpointLoadMetricStats_total_metric_value(const envoy_api_v2_endpoint_EndpointLoadMetricStats *msg) { return UPB_FIELD_AT(msg, double, UPB_SIZE(8, 8)); } + +UPB_INLINE void envoy_api_v2_endpoint_EndpointLoadMetricStats_set_metric_name(envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, upb_strview value) { + UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(16, 16)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_EndpointLoadMetricStats_set_num_requests_finished_with_metric(envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_EndpointLoadMetricStats_set_total_metric_value(envoy_api_v2_endpoint_EndpointLoadMetricStats *msg, double value) { + UPB_FIELD_AT(msg, double, UPB_SIZE(8, 8)) = value; +} + + +/* envoy.api.v2.endpoint.ClusterStats */ + +UPB_INLINE envoy_api_v2_endpoint_ClusterStats *envoy_api_v2_endpoint_ClusterStats_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_ClusterStats *)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats *envoy_api_v2_endpoint_ClusterStats_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_ClusterStats *ret = envoy_api_v2_endpoint_ClusterStats_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_ClusterStats_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_ClusterStats_serialize(const envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_ClusterStats_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_api_v2_endpoint_ClusterStats_cluster_name(const envoy_api_v2_endpoint_ClusterStats *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); } +UPB_INLINE const envoy_api_v2_endpoint_UpstreamLocalityStats* const* envoy_api_v2_endpoint_ClusterStats_upstream_locality_stats(const envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_UpstreamLocalityStats* const*)_upb_array_accessor(msg, UPB_SIZE(20, 32), len); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_ClusterStats_total_dropped_requests(const envoy_api_v2_endpoint_ClusterStats *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } +UPB_INLINE const struct google_protobuf_Duration* envoy_api_v2_endpoint_ClusterStats_load_report_interval(const envoy_api_v2_endpoint_ClusterStats *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(16, 24)); } +UPB_INLINE const envoy_api_v2_endpoint_ClusterStats_DroppedRequests* const* envoy_api_v2_endpoint_ClusterStats_dropped_requests(const envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { return (const envoy_api_v2_endpoint_ClusterStats_DroppedRequests* const*)_upb_array_accessor(msg, UPB_SIZE(24, 40), len); } + +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_set_cluster_name(envoy_api_v2_endpoint_ClusterStats *msg, upb_strview value) { + UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats** envoy_api_v2_endpoint_ClusterStats_mutable_upstream_locality_stats(envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_UpstreamLocalityStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 32), len); +} +UPB_INLINE envoy_api_v2_endpoint_UpstreamLocalityStats** envoy_api_v2_endpoint_ClusterStats_resize_upstream_locality_stats(envoy_api_v2_endpoint_ClusterStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_UpstreamLocalityStats**)_upb_array_resize_accessor(msg, UPB_SIZE(20, 32), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_UpstreamLocalityStats* envoy_api_v2_endpoint_ClusterStats_add_upstream_locality_stats(envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_UpstreamLocalityStats* sub = (struct envoy_api_v2_endpoint_UpstreamLocalityStats*)upb_msg_new(&envoy_api_v2_endpoint_UpstreamLocalityStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(20, 32), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_set_total_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_set_load_report_interval(envoy_api_v2_endpoint_ClusterStats *msg, struct google_protobuf_Duration* value) { + UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(16, 24)) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_api_v2_endpoint_ClusterStats_mutable_load_report_interval(envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_api_v2_endpoint_ClusterStats_load_report_interval(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_api_v2_endpoint_ClusterStats_set_load_report_interval(msg, sub); + } + return sub; +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests** envoy_api_v2_endpoint_ClusterStats_mutable_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, size_t *len) { + return (envoy_api_v2_endpoint_ClusterStats_DroppedRequests**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 40), len); +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests** envoy_api_v2_endpoint_ClusterStats_resize_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, size_t len, upb_arena *arena) { + return (envoy_api_v2_endpoint_ClusterStats_DroppedRequests**)_upb_array_resize_accessor(msg, UPB_SIZE(24, 40), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests* envoy_api_v2_endpoint_ClusterStats_add_dropped_requests(envoy_api_v2_endpoint_ClusterStats *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests* sub = (struct envoy_api_v2_endpoint_ClusterStats_DroppedRequests*)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(24, 40), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.api.v2.endpoint.ClusterStats.DroppedRequests */ + +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests *envoy_api_v2_endpoint_ClusterStats_DroppedRequests_new(upb_arena *arena) { + return (envoy_api_v2_endpoint_ClusterStats_DroppedRequests *)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, arena); +} +UPB_INLINE envoy_api_v2_endpoint_ClusterStats_DroppedRequests *envoy_api_v2_endpoint_ClusterStats_DroppedRequests_parsenew(upb_strview buf, upb_arena *arena) { + envoy_api_v2_endpoint_ClusterStats_DroppedRequests *ret = envoy_api_v2_endpoint_ClusterStats_DroppedRequests_new(arena); + return (ret && upb_decode(buf, ret, &envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_api_v2_endpoint_ClusterStats_DroppedRequests_serialize(const envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_api_v2_endpoint_ClusterStats_DroppedRequests_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_api_v2_endpoint_ClusterStats_DroppedRequests_category(const envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg) { return UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)); } +UPB_INLINE uint64_t envoy_api_v2_endpoint_ClusterStats_DroppedRequests_dropped_count(const envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg) { return UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)); } + +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_category(envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg, upb_strview value) { + UPB_FIELD_AT(msg, upb_strview, UPB_SIZE(8, 8)) = value; +} +UPB_INLINE void envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_dropped_count(envoy_api_v2_endpoint_ClusterStats_DroppedRequests *msg, uint64_t value) { + UPB_FIELD_AT(msg, uint64_t, UPB_SIZE(0, 0)) = value; +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_API_V2_ENDPOINT_LOAD_REPORT_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c new file mode 100644 index 00000000000..a6e4bd2d18b --- /dev/null +++ b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.c @@ -0,0 +1,52 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/load_stats/v2/lrs.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/service/load_stats/v2/lrs.upb.h" +#include "envoy/api/v2/core/base.upb.h" +#include "envoy/api/v2/endpoint/load_report.upb.h" +#include "google/protobuf/duration.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_service_load_stats_v2_LoadStatsRequest_submsgs[2] = { + &envoy_api_v2_core_Node_msginit, + &envoy_api_v2_endpoint_ClusterStats_msginit, +}; + +static const upb_msglayout_field envoy_service_load_stats_v2_LoadStatsRequest__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 1}, + {2, UPB_SIZE(4, 8), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_service_load_stats_v2_LoadStatsRequest_msginit = { + &envoy_service_load_stats_v2_LoadStatsRequest_submsgs[0], + &envoy_service_load_stats_v2_LoadStatsRequest__fields[0], + UPB_SIZE(8, 16), 2, false, +}; + +static const upb_msglayout *const envoy_service_load_stats_v2_LoadStatsResponse_submsgs[1] = { + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_service_load_stats_v2_LoadStatsResponse__fields[3] = { + {1, UPB_SIZE(8, 16), 0, 0, 9, 3}, + {2, UPB_SIZE(4, 8), 0, 0, 11, 1}, + {3, UPB_SIZE(0, 0), 0, 0, 8, 1}, +}; + +const upb_msglayout envoy_service_load_stats_v2_LoadStatsResponse_msginit = { + &envoy_service_load_stats_v2_LoadStatsResponse_submsgs[0], + &envoy_service_load_stats_v2_LoadStatsResponse__fields[0], + UPB_SIZE(12, 24), 3, false, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h new file mode 100644 index 00000000000..99db767a8a1 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/service/load_stats/v2/lrs.upb.h @@ -0,0 +1,132 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/load_stats/v2/lrs.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_SERVICE_LOAD_STATS_V2_LRS_PROTO_UPB_H_ +#define ENVOY_SERVICE_LOAD_STATS_V2_LRS_PROTO_UPB_H_ + +#include "upb/generated_util.h" + +#include "upb/msg.h" + +#include "upb/decode.h" +#include "upb/encode.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_service_load_stats_v2_LoadStatsRequest; +struct envoy_service_load_stats_v2_LoadStatsResponse; +typedef struct envoy_service_load_stats_v2_LoadStatsRequest envoy_service_load_stats_v2_LoadStatsRequest; +typedef struct envoy_service_load_stats_v2_LoadStatsResponse envoy_service_load_stats_v2_LoadStatsResponse; +extern const upb_msglayout envoy_service_load_stats_v2_LoadStatsRequest_msginit; +extern const upb_msglayout envoy_service_load_stats_v2_LoadStatsResponse_msginit; +struct envoy_api_v2_core_Node; +struct envoy_api_v2_endpoint_ClusterStats; +struct google_protobuf_Duration; +extern const upb_msglayout envoy_api_v2_core_Node_msginit; +extern const upb_msglayout envoy_api_v2_endpoint_ClusterStats_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; + +/* Enums */ + + +/* envoy.service.load_stats.v2.LoadStatsRequest */ + +UPB_INLINE envoy_service_load_stats_v2_LoadStatsRequest *envoy_service_load_stats_v2_LoadStatsRequest_new(upb_arena *arena) { + return (envoy_service_load_stats_v2_LoadStatsRequest *)upb_msg_new(&envoy_service_load_stats_v2_LoadStatsRequest_msginit, arena); +} +UPB_INLINE envoy_service_load_stats_v2_LoadStatsRequest *envoy_service_load_stats_v2_LoadStatsRequest_parsenew(upb_strview buf, upb_arena *arena) { + envoy_service_load_stats_v2_LoadStatsRequest *ret = envoy_service_load_stats_v2_LoadStatsRequest_new(arena); + return (ret && upb_decode(buf, ret, &envoy_service_load_stats_v2_LoadStatsRequest_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_service_load_stats_v2_LoadStatsRequest_serialize(const envoy_service_load_stats_v2_LoadStatsRequest *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_load_stats_v2_LoadStatsRequest_msginit, arena, len); +} + +UPB_INLINE const struct envoy_api_v2_core_Node* envoy_service_load_stats_v2_LoadStatsRequest_node(const envoy_service_load_stats_v2_LoadStatsRequest *msg) { return UPB_FIELD_AT(msg, const struct envoy_api_v2_core_Node*, UPB_SIZE(0, 0)); } +UPB_INLINE const struct envoy_api_v2_endpoint_ClusterStats* const* envoy_service_load_stats_v2_LoadStatsRequest_cluster_stats(const envoy_service_load_stats_v2_LoadStatsRequest *msg, size_t *len) { return (const struct envoy_api_v2_endpoint_ClusterStats* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE void envoy_service_load_stats_v2_LoadStatsRequest_set_node(envoy_service_load_stats_v2_LoadStatsRequest *msg, struct envoy_api_v2_core_Node* value) { + UPB_FIELD_AT(msg, struct envoy_api_v2_core_Node*, UPB_SIZE(0, 0)) = value; +} +UPB_INLINE struct envoy_api_v2_core_Node* envoy_service_load_stats_v2_LoadStatsRequest_mutable_node(envoy_service_load_stats_v2_LoadStatsRequest *msg, upb_arena *arena) { + struct envoy_api_v2_core_Node* sub = (struct envoy_api_v2_core_Node*)envoy_service_load_stats_v2_LoadStatsRequest_node(msg); + if (sub == NULL) { + sub = (struct envoy_api_v2_core_Node*)upb_msg_new(&envoy_api_v2_core_Node_msginit, arena); + if (!sub) return NULL; + envoy_service_load_stats_v2_LoadStatsRequest_set_node(msg, sub); + } + return sub; +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats** envoy_service_load_stats_v2_LoadStatsRequest_mutable_cluster_stats(envoy_service_load_stats_v2_LoadStatsRequest *msg, size_t *len) { + return (struct envoy_api_v2_endpoint_ClusterStats**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats** envoy_service_load_stats_v2_LoadStatsRequest_resize_cluster_stats(envoy_service_load_stats_v2_LoadStatsRequest *msg, size_t len, upb_arena *arena) { + return (struct envoy_api_v2_endpoint_ClusterStats**)_upb_array_resize_accessor(msg, UPB_SIZE(4, 8), len, UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, arena); +} +UPB_INLINE struct envoy_api_v2_endpoint_ClusterStats* envoy_service_load_stats_v2_LoadStatsRequest_add_cluster_stats(envoy_service_load_stats_v2_LoadStatsRequest *msg, upb_arena *arena) { + struct envoy_api_v2_endpoint_ClusterStats* sub = (struct envoy_api_v2_endpoint_ClusterStats*)upb_msg_new(&envoy_api_v2_endpoint_ClusterStats_msginit, arena); + bool ok = _upb_array_append_accessor( + msg, UPB_SIZE(4, 8), UPB_SIZE(4, 8), UPB_TYPE_MESSAGE, &sub, arena); + if (!ok) return NULL; + return sub; +} + + +/* envoy.service.load_stats.v2.LoadStatsResponse */ + +UPB_INLINE envoy_service_load_stats_v2_LoadStatsResponse *envoy_service_load_stats_v2_LoadStatsResponse_new(upb_arena *arena) { + return (envoy_service_load_stats_v2_LoadStatsResponse *)upb_msg_new(&envoy_service_load_stats_v2_LoadStatsResponse_msginit, arena); +} +UPB_INLINE envoy_service_load_stats_v2_LoadStatsResponse *envoy_service_load_stats_v2_LoadStatsResponse_parsenew(upb_strview buf, upb_arena *arena) { + envoy_service_load_stats_v2_LoadStatsResponse *ret = envoy_service_load_stats_v2_LoadStatsResponse_new(arena); + return (ret && upb_decode(buf, ret, &envoy_service_load_stats_v2_LoadStatsResponse_msginit)) ? ret : NULL; +} +UPB_INLINE char *envoy_service_load_stats_v2_LoadStatsResponse_serialize(const envoy_service_load_stats_v2_LoadStatsResponse *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_load_stats_v2_LoadStatsResponse_msginit, arena, len); +} + +UPB_INLINE upb_strview const* envoy_service_load_stats_v2_LoadStatsResponse_clusters(const envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE const struct google_protobuf_Duration* envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, const struct google_protobuf_Duration*, UPB_SIZE(4, 8)); } +UPB_INLINE bool envoy_service_load_stats_v2_LoadStatsResponse_report_endpoint_granularity(const envoy_service_load_stats_v2_LoadStatsResponse *msg) { return UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)); } + +UPB_INLINE upb_strview* envoy_service_load_stats_v2_LoadStatsResponse_mutable_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE upb_strview* envoy_service_load_stats_v2_LoadStatsResponse_resize_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor(msg, UPB_SIZE(8, 16), len, UPB_SIZE(8, 16), UPB_TYPE_STRING, arena); +} +UPB_INLINE bool envoy_service_load_stats_v2_LoadStatsResponse_add_clusters(envoy_service_load_stats_v2_LoadStatsResponse *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor( + msg, UPB_SIZE(8, 16), UPB_SIZE(8, 16), UPB_TYPE_STRING, &val, arena); +} +UPB_INLINE void envoy_service_load_stats_v2_LoadStatsResponse_set_load_reporting_interval(envoy_service_load_stats_v2_LoadStatsResponse *msg, struct google_protobuf_Duration* value) { + UPB_FIELD_AT(msg, struct google_protobuf_Duration*, UPB_SIZE(4, 8)) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_service_load_stats_v2_LoadStatsResponse_mutable_load_reporting_interval(envoy_service_load_stats_v2_LoadStatsResponse *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_service_load_stats_v2_LoadStatsResponse_set_load_reporting_interval(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_load_stats_v2_LoadStatsResponse_set_report_endpoint_granularity(envoy_service_load_stats_v2_LoadStatsResponse *msg, bool value) { + UPB_FIELD_AT(msg, bool, UPB_SIZE(0, 0)) = value; +} + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_SERVICE_LOAD_STATS_V2_LRS_PROTO_UPB_H_ */ diff --git a/src/core/lib/gpr/time_posix.cc b/src/core/lib/gpr/time_posix.cc index 1b3e36486fc..b5a47673676 100644 --- a/src/core/lib/gpr/time_posix.cc +++ b/src/core/lib/gpr/time_posix.cc @@ -108,6 +108,9 @@ static gpr_timespec now_impl(gpr_clock_type clock) { now.clock_type = clock; switch (clock) { case GPR_CLOCK_REALTIME: + // gettimeofday(...) function may return with a value whose tv_usec is + // greater than 1e6 on iOS The case is resolved with the guard at end of + // this function. gettimeofday(&now_tv, nullptr); now.tv_sec = now_tv.tv_sec; now.tv_nsec = now_tv.tv_usec * 1000; @@ -124,6 +127,16 @@ static gpr_timespec now_impl(gpr_clock_type clock) { abort(); } + // Guard the tv_nsec field in valid range for all clock types + while (GPR_UNLIKELY(now.tv_nsec >= 1e9)) { + now.tv_sec++; + now.tv_nsec -= 1e9; + } + while (GPR_UNLIKELY(now.tv_nsec < 0)) { + now.tv_sec--; + now.tv_nsec += 1e9; + } + return now; } #endif diff --git a/src/core/lib/gprpp/map.h b/src/core/lib/gprpp/map.h new file mode 100644 index 00000000000..b210c26cbff --- /dev/null +++ b/src/core/lib/gprpp/map.h @@ -0,0 +1,419 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_MAP_H +#define GRPC_CORE_LIB_GPRPP_MAP_H + +#include + +#include +#include +#include +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/pair.h" + +namespace grpc_core { +struct StringLess { + bool operator()(const char* a, const char* b) const { + return strcmp(a, b) < 0; + } + bool operator()(const UniquePtr& k1, const UniquePtr& k2) { + return strcmp(k1.get(), k2.get()) < 0; + } +}; + +namespace testing { +class MapTest; +} + +// Alternative map implementation for grpc_core +template > +class Map { + public: + typedef Key key_type; + typedef T mapped_type; + typedef Pair value_type; + typedef Compare key_compare; + class iterator; + + ~Map() { clear(); } + + T& operator[](key_type&& key); + T& operator[](const key_type& key); + iterator find(const key_type& k); + size_t erase(const key_type& key); + // Removes the current entry and points to the next one + iterator erase(iterator iter); + + size_t size() { return size_; } + + template + Pair emplace(Args&&... args); + + Pair insert(value_type&& pair) { + return emplace(std::move(pair)); + } + + Pair insert(const value_type& pair) { return emplace(pair); } + + bool empty() const { return root_ == nullptr; } + + void clear() { + auto iter = begin(); + while (!empty()) { + iter = erase(iter); + } + } + + iterator begin() { + Entry* curr = GetMinEntry(root_); + return iterator(this, curr); + } + + iterator end() { return iterator(this, nullptr); } + + private: + friend class testing::MapTest; + struct Entry { + explicit Entry(value_type&& pair) : pair(std::move(pair)) {} + value_type pair; + Entry* left = nullptr; + Entry* right = nullptr; + int32_t height = 1; + }; + + static int32_t EntryHeight(const Entry* e) { + return e == nullptr ? 0 : e->height; + } + + static Entry* GetMinEntry(Entry* e); + Entry* InOrderSuccessor(const Entry* e) const; + static Entry* RotateLeft(Entry* e); + static Entry* RotateRight(Entry* e); + static Entry* RebalanceTreeAfterInsertion(Entry* root, const key_type& k); + static Entry* RebalanceTreeAfterDeletion(Entry* root); + // Returns a pair with the first value being an iterator pointing to the + // inserted entry and the second value being the new root of the subtree + // after a rebalance + Pair InsertRecursive(Entry* root, value_type&& p); + static Entry* RemoveRecursive(Entry* root, const key_type& k); + // Return 0 if lhs = rhs + // 1 if lhs > rhs + // -1 if lhs < rhs + static int CompareKeys(const Key& lhs, const Key& rhs); + + Entry* root_ = nullptr; + size_t size_ = 0; +}; + +template +class Map::iterator + : public std::iterator, int32_t, + Pair*, Pair&> { + public: + iterator(const iterator& iter) : curr_(iter.curr_), map_(iter.map_) {} + bool operator==(const iterator& rhs) const { return (curr_ == rhs.curr_); } + bool operator!=(const iterator& rhs) const { return (curr_ != rhs.curr_); } + + iterator& operator++() { + curr_ = map_->InOrderSuccessor(curr_); + return *this; + } + + iterator operator++(int) { + Entry* prev = curr_; + curr_ = map_->InOrderSuccessor(curr_); + return iterator(map_, prev); + } + + iterator& operator=(const iterator& other) { + if (this != &other) { + this->curr_ = other.curr_; + this->map_ = other.map_; + } + return *this; + } + + // operator*() + value_type& operator*() { return curr_->pair; } + const value_type& operator*() const { return curr_->pair; } + + // operator->() + value_type* operator->() { return &curr_->pair; } + value_type const* operator->() const { return &curr_->pair; } + + private: + friend class Map; + using GrpcMap = typename ::grpc_core::Map; + iterator(GrpcMap* map, Entry* curr) : curr_(curr), map_(map) {} + Entry* curr_; + GrpcMap* map_; +}; + +template +T& Map::operator[](key_type&& key) { + auto iter = find(key); + if (iter == end()) { + return emplace(std::move(key), T()).first->second; + } + return iter->second; +} + +template +T& Map::operator[](const key_type& key) { + auto iter = find(key); + if (iter == end()) { + return emplace(key, T()).first->second; + } + return iter->second; +} + +template +typename Map::iterator Map::find( + const key_type& k) { + Entry* iter = root_; + while (iter != nullptr) { + int comp = CompareKeys(iter->pair.first, k); + if (comp == 0) { + return iterator(this, iter); + } else if (comp < 0) { + iter = iter->right; + } else { + iter = iter->left; + } + } + return end(); +} + +template +template +typename ::grpc_core::Pair::iterator, bool> +Map::emplace(Args&&... args) { + Pair pair(std::forward(args)...); + iterator ret = find(pair.first); + bool insertion = false; + if (ret == end()) { + Pair p = InsertRecursive(root_, std::move(pair)); + root_ = p.second; + ret = p.first; + insertion = true; + size_++; + } + return MakePair(ret, insertion); +} + +template +size_t Map::erase(const key_type& key) { + iterator it = find(key); + if (it == end()) return 0; + erase(it); + return 1; +} + +// TODO(mhaidry): Modify erase to use the iterator location +// to create an efficient erase method +template +typename Map::iterator Map::erase( + iterator iter) { + if (iter == end()) return iter; + key_type& del_key = iter->first; + iter++; + root_ = RemoveRecursive(root_, del_key); + size_--; + return iter; +} + +template +typename Map::Entry* Map::InOrderSuccessor( + const Entry* e) const { + if (e->right != nullptr) { + return GetMinEntry(e->right); + } + Entry* successor = nullptr; + Entry* iter = root_; + while (iter != nullptr) { + int comp = CompareKeys(iter->pair.first, e->pair.first); + if (comp > 0) { + successor = iter; + iter = iter->left; + } else if (comp < 0) { + iter = iter->right; + } else + break; + } + return successor; +} + +// Returns a pair with the first value being an iterator pointing to the +// inserted entry and the second value being the new root of the subtree +// after a rebalance +template +typename ::grpc_core::Pair::iterator, + typename Map::Entry*> +Map::InsertRecursive(Entry* root, value_type&& p) { + if (root == nullptr) { + Entry* e = New(std::move(p)); + return MakePair(iterator(this, e), e); + } + int comp = CompareKeys(root->pair.first, p.first); + if (comp > 0) { + Pair ret = InsertRecursive(root->left, std::move(p)); + root->left = ret.second; + ret.second = RebalanceTreeAfterInsertion(root, ret.first->first); + return ret; + } else if (comp < 0) { + Pair ret = InsertRecursive(root->right, std::move(p)); + root->right = ret.second; + ret.second = RebalanceTreeAfterInsertion(root, ret.first->first); + return ret; + } else { + root->pair = std::move(p); + return MakePair(iterator(this, root), root); + } +} + +template +typename Map::Entry* Map::GetMinEntry( + Entry* e) { + if (e != nullptr) { + while (e->left != nullptr) { + e = e->left; + } + } + return e; +} + +template +typename Map::Entry* Map::RotateLeft( + Entry* e) { + Entry* rightChild = e->right; + Entry* rightLeftChild = rightChild->left; + rightChild->left = e; + e->right = rightLeftChild; + e->height = 1 + GPR_MAX(EntryHeight(e->left), EntryHeight(e->right)); + rightChild->height = 1 + GPR_MAX(EntryHeight(rightChild->left), + EntryHeight(rightChild->right)); + return rightChild; +} + +template +typename Map::Entry* Map::RotateRight( + Entry* e) { + Entry* leftChild = e->left; + Entry* leftRightChild = leftChild->right; + leftChild->right = e; + e->left = leftRightChild; + e->height = 1 + GPR_MAX(EntryHeight(e->left), EntryHeight(e->right)); + leftChild->height = + 1 + GPR_MAX(EntryHeight(leftChild->left), EntryHeight(leftChild->right)); + return leftChild; +} + +template +typename Map::Entry* +Map::RebalanceTreeAfterInsertion(Entry* root, + const key_type& k) { + root->height = 1 + GPR_MAX(EntryHeight(root->left), EntryHeight(root->right)); + int32_t heightDifference = EntryHeight(root->left) - EntryHeight(root->right); + if (heightDifference > 1 && CompareKeys(root->left->pair.first, k) > 0) { + return RotateRight(root); + } + if (heightDifference < -1 && CompareKeys(root->right->pair.first, k) < 0) { + return RotateLeft(root); + } + if (heightDifference > 1 && CompareKeys(root->left->pair.first, k) < 0) { + root->left = RotateLeft(root->left); + return RotateRight(root); + } + if (heightDifference < -1 && CompareKeys(root->right->pair.first, k) > 0) { + root->right = RotateRight(root->right); + return RotateLeft(root); + } + return root; +} + +template +typename Map::Entry* +Map::RebalanceTreeAfterDeletion(Entry* root) { + root->height = 1 + GPR_MAX(EntryHeight(root->left), EntryHeight(root->right)); + int32_t heightDifference = EntryHeight(root->left) - EntryHeight(root->right); + if (heightDifference > 1) { + int leftHeightDifference = + EntryHeight(root->left->left) - EntryHeight(root->left->right); + if (leftHeightDifference < 0) { + root->left = RotateLeft(root->left); + } + return RotateRight(root); + } + if (heightDifference < -1) { + int rightHeightDifference = + EntryHeight(root->right->left) - EntryHeight(root->right->right); + if (rightHeightDifference > 0) { + root->right = RotateRight(root->right); + } + return RotateLeft(root); + } + return root; +} + +template +typename Map::Entry* Map::RemoveRecursive( + Entry* root, const key_type& k) { + if (root == nullptr) return root; + int comp = CompareKeys(root->pair.first, k); + if (comp > 0) { + root->left = RemoveRecursive(root->left, k); + } else if (comp < 0) { + root->right = RemoveRecursive(root->right, k); + } else { + Entry* ret; + if (root->left == nullptr) { + ret = root->right; + Delete(root); + return ret; + } else if (root->right == nullptr) { + ret = root->left; + Delete(root); + return ret; + } else { + ret = root->right; + while (ret->left != nullptr) { + ret = ret->left; + } + root->pair.swap(ret->pair); + root->right = RemoveRecursive(root->right, ret->pair.first); + } + } + return RebalanceTreeAfterDeletion(root); +} + +template +int Map::CompareKeys(const key_type& lhs, + const key_type& rhs) { + key_compare compare; + bool left_comparison = compare(lhs, rhs); + bool right_comparison = compare(rhs, lhs); + // Both values are equal + if (!left_comparison && !right_comparison) { + return 0; + } + return left_comparison ? -1 : 1; +} +} // namespace grpc_core +#endif /* GRPC_CORE_LIB_GPRPP_MAP_H */ diff --git a/src/core/lib/gprpp/pair.h b/src/core/lib/gprpp/pair.h new file mode 100644 index 00000000000..ca8294cc7bb --- /dev/null +++ b/src/core/lib/gprpp/pair.h @@ -0,0 +1,38 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPC_CORE_LIB_GPRPP_PAIR_H +#define GRPC_CORE_LIB_GPRPP_PAIR_H + +#include + +#include + +namespace grpc_core { +template +using Pair = std::pair; + +template +inline Pair::type, typename std::decay::type> +MakePair(T1&& u, T2&& v) { + typedef typename std::decay::type V1; + typedef typename std::decay::type V2; + return Pair(std::forward(u), std::forward(v)); +} +} // namespace grpc_core +#endif /* GRPC_CORE_LIB_GPRPP_PAIR_H */ diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index cf21c4fc511..2fda160f68a 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -192,4 +192,11 @@ void CFStreamHandle::Unref(const char* file, int line, const char* reason) { } } +#else + +/* Creating a dummy function so that the grpc_cfstream library will be + * non-empty. + */ +void CFStreamDummy() {} + #endif diff --git a/src/core/lib/iomgr/iomgr_custom.cc b/src/core/lib/iomgr/iomgr_custom.cc index 56363c35fd6..f5ac8a0670a 100644 --- a/src/core/lib/iomgr/iomgr_custom.cc +++ b/src/core/lib/iomgr/iomgr_custom.cc @@ -49,6 +49,8 @@ static bool iomgr_platform_add_closure_to_background_poller( return false; } +bool g_custom_iomgr_enabled = false; + static grpc_iomgr_platform_vtable vtable = { iomgr_platform_init, iomgr_platform_flush, @@ -61,6 +63,7 @@ void grpc_custom_iomgr_init(grpc_socket_vtable* socket, grpc_custom_resolver_vtable* resolver, grpc_custom_timer_vtable* timer, grpc_custom_poller_vtable* poller) { + g_custom_iomgr_enabled = true; grpc_custom_endpoint_init(socket); grpc_custom_timer_init(timer); grpc_custom_pollset_init(poller); diff --git a/src/core/lib/iomgr/iomgr_custom.h b/src/core/lib/iomgr/iomgr_custom.h index 57cc2f9b923..e6a88843e5c 100644 --- a/src/core/lib/iomgr/iomgr_custom.h +++ b/src/core/lib/iomgr/iomgr_custom.h @@ -39,6 +39,8 @@ extern gpr_thd_id g_init_thread; #define GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD() #endif /* GRPC_CUSTOM_IOMGR_THREAD_CHECK */ +extern bool g_custom_iomgr_enabled; + void grpc_custom_iomgr_init(grpc_socket_vtable* socket, grpc_custom_resolver_vtable* resolver, grpc_custom_timer_vtable* timer, diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index ccb4c31e8c9..d387de5b13c 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -88,6 +88,15 @@ #ifdef LINUX_VERSION_CODE #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) #define GRPC_HAVE_TCP_USER_TIMEOUT +#ifdef __GLIBC_PREREQ +#if !(__GLIBC_PREREQ(2, 17)) +/* + * TCP_USER_TIMEOUT wasn't imported to glibc until 2.17. Use Linux system + * header instead. + */ +#define GRPC_LINUX_TCP_H 1 +#endif /* __GLIBC_PREREQ(2, 17) */ +#endif /* ifdef __GLIBC_PREREQ */ #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37) */ #endif /* LINUX_VERSION_CODE */ #ifndef __GLIBC__ diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 4c337a05210..ea0adb1f6a6 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -30,7 +30,11 @@ #include #include #include +#ifdef GRPC_LINUX_TCP_H +#include +#else #include +#endif #include #include #include diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc index 824db07fbfd..baef3886530 100644 --- a/src/core/lib/iomgr/tcp_server_posix.cc +++ b/src/core/lib/iomgr/tcp_server_posix.cc @@ -217,6 +217,19 @@ static void on_read(void* arg, grpc_error* err) { } } + /* For UNIX sockets, the accept call might not fill up the member sun_path + * of sockaddr_un, so explicitly call getsockname to get it. */ + if (grpc_is_unix_socket(&addr)) { + memset(&addr, 0, sizeof(addr)); + addr.len = static_cast(sizeof(struct sockaddr_storage)); + if (getsockname(fd, reinterpret_cast(addr.addr), + &(addr.len)) < 0) { + gpr_log(GPR_ERROR, "Failed getsockname: %s", strerror(errno)); + close(fd); + goto error; + } + } + grpc_set_socket_no_sigpipe_if_possible(fd); addr_str = grpc_sockaddr_to_uri(&addr); diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index 7b464651ea1..60d34ef897f 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -88,6 +88,18 @@ static grpc_error* enable_loopback_fast_path(SOCKET sock) { : GRPC_WSA_ERROR(status, "WSAIoctl(SIO_LOOPBACK_FAST_PATH)"); } +static grpc_error* enable_socket_low_latency(SOCKET sock) { + int status; + BOOL param = TRUE; + status = ::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(¶m), sizeof(param)); + if (status == SOCKET_ERROR) { + status = WSAGetLastError(); + } + return status == 0 ? GRPC_ERROR_NONE + : GRPC_WSA_ERROR(status, "setsockopt(TCP_NODELAY)"); +} + grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { grpc_error* err; err = grpc_tcp_set_non_block(sock); @@ -96,6 +108,8 @@ grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { if (err != GRPC_ERROR_NONE) return err; err = enable_loopback_fast_path(sock); if (err != GRPC_ERROR_NONE) return err; + err = enable_socket_low_latency(sock); + if (err != GRPC_ERROR_NONE) return err; return GRPC_ERROR_NONE; } diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index b6a79c1030e..adc76cb1740 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -172,7 +172,6 @@ static int is_metadata_server_reachable() { detector.pollent = grpc_polling_entity_create_from_pollset(pollset); detector.is_done = 0; detector.success = 0; - memset(&detector.response, 0, sizeof(detector.response)); memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = (char*)GRPC_COMPUTE_ENGINE_DETECTION_HOST; request.http.path = (char*)"/"; diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/src/core/lib/security/credentials/jwt/jwt_verifier.cc index d573c30787d..5b120eddb43 100644 --- a/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -624,9 +624,8 @@ static int verify_jwt_signature(EVP_PKEY* key, const char* alg, gpr_log(GPR_ERROR, "EVP_DigestVerifyUpdate failed."); goto end; } - if (EVP_DigestVerifyFinal( - md_ctx, const_cast(GRPC_SLICE_START_PTR(signature)), - GRPC_SLICE_LENGTH(signature)) != 1) { + if (EVP_DigestVerifyFinal(md_ctx, GRPC_SLICE_START_PTR(signature), + GRPC_SLICE_LENGTH(signature)) != 1) { gpr_log(GPR_ERROR, "JWT signature verification failed."); goto end; } diff --git a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc index 8a00bbb82ed..ad492f361aa 100644 --- a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +++ b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc @@ -44,24 +44,15 @@ namespace { grpc_error* ssl_check_peer( const char* peer_name, const tsi_peer* peer, grpc_core::RefCountedPtr* auth_context) { -#if TSI_OPENSSL_ALPN_SUPPORT - /* Check the ALPN if ALPN is supported. */ - const tsi_peer_property* p = - tsi_peer_get_property_by_name(peer, TSI_SSL_ALPN_SELECTED_PROTOCOL); - if (p == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: missing selected ALPN property."); - } - if (!grpc_chttp2_is_alpn_version_supported(p->value.data, p->value.length)) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Cannot check peer: invalid ALPN value."); + grpc_error* error = grpc_ssl_check_alpn(peer); + if (error != GRPC_ERROR_NONE) { + return error; } -#endif /* TSI_OPENSSL_ALPN_SUPPORT */ /* Check the peer name if specified. */ if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { char* msg; gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name); - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); + error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); gpr_free(msg); return error; } diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc index fdb584da68f..b67d4f12252 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -73,6 +73,7 @@ static void do_basic_init(void) { g_shutting_down = false; grpc_register_built_in_plugins(); grpc_cq_global_init(); + gpr_time_init(); g_initializations = 0; } @@ -132,7 +133,6 @@ void grpc_init(void) { } grpc_core::Fork::GlobalInit(); grpc_fork_handlers_auto_register(); - gpr_time_init(); gpr_arena_init(); grpc_stats_init(); grpc_slice_intern_init(); diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc index bf2e6c90846..8aeadaf5078 100644 --- a/src/core/lib/surface/version.cc +++ b/src/core/lib/surface/version.cc @@ -25,4 +25,4 @@ const char* grpc_version_string(void) { return "7.0.0"; } -const char* grpc_g_stands_for(void) { return "godric"; } +const char* grpc_g_stands_for(void) { return "gandalf"; } diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index 8be0b91b654..09306110c63 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -29,6 +29,7 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/slice/slice_internal.h" @@ -243,25 +244,26 @@ void grpc_transport_stream_op_batch_finish_with_failure( GRPC_ERROR_UNREF(error); } -typedef struct { +struct made_transport_op { grpc_closure outer_on_complete; - grpc_closure* inner_on_complete; + grpc_closure* inner_on_complete = nullptr; grpc_transport_op op; -} made_transport_op; + made_transport_op() { + memset(&outer_on_complete, 0, sizeof(outer_on_complete)); + } +}; static void destroy_made_transport_op(void* arg, grpc_error* error) { made_transport_op* op = static_cast(arg); GRPC_CLOSURE_SCHED(op->inner_on_complete, GRPC_ERROR_REF(error)); - gpr_free(op); + grpc_core::Delete(op); } grpc_transport_op* grpc_make_transport_op(grpc_closure* on_complete) { - made_transport_op* op = - static_cast(gpr_malloc(sizeof(*op))); + made_transport_op* op = grpc_core::New(); GRPC_CLOSURE_INIT(&op->outer_on_complete, destroy_made_transport_op, op, grpc_schedule_on_exec_ctx); op->inner_on_complete = on_complete; - memset(&op->op, 0, sizeof(op->op)); op->op.on_consumed = &op->outer_on_complete; return &op->op; } diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 9d4b5615e57..8631a1af81f 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -273,40 +273,40 @@ struct grpc_transport_stream_op_batch_payload { /** Transport op: a set of operations to perform on a transport as a whole */ typedef struct grpc_transport_op { /** Called when processing of this op is done. */ - grpc_closure* on_consumed; + grpc_closure* on_consumed = nullptr; /** connectivity monitoring - set connectivity_state to NULL to unsubscribe */ - grpc_closure* on_connectivity_state_change; - grpc_connectivity_state* connectivity_state; + grpc_closure* on_connectivity_state_change = nullptr; + grpc_connectivity_state* connectivity_state = nullptr; /** should the transport be disconnected * Error contract: the transport that gets this op must cause * disconnect_with_error to be unref'ed after processing it */ - grpc_error* disconnect_with_error; + grpc_error* disconnect_with_error = nullptr; /** what should the goaway contain? * Error contract: the transport that gets this op must cause * goaway_error to be unref'ed after processing it */ - grpc_error* goaway_error; + grpc_error* goaway_error = nullptr; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its user_data argument set to set_accept_stream_user_data */ - bool set_accept_stream; + bool set_accept_stream = false; void (*set_accept_stream_fn)(void* user_data, grpc_transport* transport, - const void* server_data); - void* set_accept_stream_user_data; + const void* server_data) = nullptr; + void* set_accept_stream_user_data = nullptr; /** add this transport to a pollset */ - grpc_pollset* bind_pollset; + grpc_pollset* bind_pollset = nullptr; /** add this transport to a pollset_set */ - grpc_pollset_set* bind_pollset_set; + grpc_pollset_set* bind_pollset_set = nullptr; /** send a ping, if either on_initiate or on_ack is not NULL */ struct { /** Ping may be delayed by the transport, on_initiate callback will be called when the ping is actually being sent. */ - grpc_closure* on_initiate; + grpc_closure* on_initiate = nullptr; /** Called when the ping ack is received */ - grpc_closure* on_ack; + grpc_closure* on_ack = nullptr; } send_ping; // If true, will reset the channel's connection backoff. - bool reset_connect_backoff; + bool reset_connect_backoff = false; /*************************************************************************** * remaining fields are initialized and used at the discretion of the diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index a31d0b30b15..db59d4d8416 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -18,8 +18,6 @@ #include -#include -#include #include #include #include @@ -41,12 +39,7 @@ #include #include #include -#include -#include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/thd.h" -#include "src/core/lib/profiling/timers.h" #include "src/core/lib/surface/completion_queue.h" namespace grpc { diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 457daa674c7..e1dca5f1a12 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -19,34 +19,38 @@ #include #include -#include +#include #include #include #include "src/cpp/client/create_channel_internal.h" namespace grpc { -class ChannelArguments; -std::shared_ptr CreateChannel( +class ChannelArguments; +} +namespace grpc_impl { +std::shared_ptr CreateChannel( const grpc::string& target, - const std::shared_ptr& creds) { - return CreateCustomChannel(target, creds, ChannelArguments()); + const std::shared_ptr& creds) { + return CreateCustomChannel(target, creds, grpc::ChannelArguments()); } -std::shared_ptr CreateCustomChannel( +std::shared_ptr CreateCustomChannel( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args) { - GrpcLibraryCodegen init_lib; // We need to call init in case of a bad creds. + const std::shared_ptr& creds, + const grpc::ChannelArguments& args) { + grpc::GrpcLibraryCodegen + init_lib; // We need to call init in case of a bad creds. return creds ? creds->CreateChannel(target, args) - : CreateChannelInternal( + : grpc::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), std::vector>()); + grpc::experimental:: + ClientInterceptorFactoryInterface>>()); } namespace experimental { @@ -61,23 +65,22 @@ namespace experimental { /// hold an object or is invalid, a lame channel (one on which all operations /// fail) is returned. /// \param args Options for channel creation. -std::shared_ptr CreateCustomChannelWithInterceptors( +std::shared_ptr CreateCustomChannelWithInterceptors( const grpc::string& target, - const std::shared_ptr& creds, - const ChannelArguments& args, + const std::shared_ptr& creds, + const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators) { return creds ? creds->CreateChannelWithInterceptors( target, args, std::move(interceptor_creators)) - : CreateChannelInternal( + : grpc::CreateChannelInternal( "", grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), - std::vector>()); + std::move(interceptor_creators)); } } // namespace experimental -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/client/create_channel_posix.cc b/src/cpp/client/create_channel_posix.cc index 3affc1ef391..6de373577eb 100644 --- a/src/cpp/client/create_channel_posix.cc +++ b/src/cpp/client/create_channel_posix.cc @@ -24,45 +24,46 @@ #include "src/cpp/client/create_channel_internal.h" -namespace grpc { +namespace grpc_impl { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -std::shared_ptr CreateInsecureChannelFromFd(const grpc::string& target, - int fd) { - internal::GrpcLibrary init_lib; +std::shared_ptr CreateInsecureChannelFromFd( + const grpc::string& target, int fd) { + grpc::internal::GrpcLibrary init_lib; init_lib.init(); - return CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr), - std::vector< - std::unique_ptr>()); + std::vector>()); } -std::shared_ptr CreateCustomInsecureChannelFromFd( - const grpc::string& target, int fd, const ChannelArguments& args) { - internal::GrpcLibrary init_lib; +std::shared_ptr CreateCustomInsecureChannelFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args) { + grpc::internal::GrpcLibrary init_lib; init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), - std::vector< - std::unique_ptr>()); + std::vector>()); } namespace experimental { -std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( - const grpc::string& target, int fd, const ChannelArguments& args, +std::shared_ptr +CreateCustomInsecureChannelWithInterceptorsFromFd( + const grpc::string& target, int fd, const grpc::ChannelArguments& args, std::vector< - std::unique_ptr> + std::unique_ptr> interceptor_creators) { - internal::GrpcLibrary init_lib; + grpc::internal::GrpcLibrary init_lib; init_lib.init(); grpc_channel_args channel_args; args.SetChannelArgs(&channel_args); - return CreateChannelInternal( + return grpc::CreateChannelInternal( "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args), std::move(interceptor_creators)); @@ -72,4 +73,4 @@ std::shared_ptr CreateCustomInsecureChannelWithInterceptorsFromFd( #endif // GPR_SUPPORT_CHANNELS_FROM_FD -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc index f61c1b5317b..41631c794f2 100644 --- a/src/cpp/client/generic_stub.cc +++ b/src/cpp/client/generic_stub.cc @@ -22,63 +22,75 @@ #include #include -namespace grpc { +namespace grpc_impl { namespace { -std::unique_ptr CallInternal( - ChannelInterface* channel, ClientContext* context, - const grpc::string& method, CompletionQueue* cq, bool start, void* tag) { - return std::unique_ptr( - internal::ClientAsyncReaderWriterFactory::Create( - channel, cq, - internal::RpcMethod(method.c_str(), - internal::RpcMethod::BIDI_STREAMING), - context, start, tag)); +std::unique_ptr CallInternal( + grpc::ChannelInterface* channel, grpc::ClientContext* context, + const grpc::string& method, grpc::CompletionQueue* cq, bool start, + void* tag) { + return std::unique_ptr( + grpc::internal::ClientAsyncReaderWriterFactory:: + Create(channel, cq, + grpc::internal::RpcMethod( + method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING), + context, start, tag)); } } // namespace // begin a call to a named method -std::unique_ptr GenericStub::Call( - ClientContext* context, const grpc::string& method, CompletionQueue* cq, - void* tag) { +std::unique_ptr GenericStub::Call( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq, void* tag) { return CallInternal(channel_.get(), context, method, cq, true, tag); } // setup a call to a named method -std::unique_ptr GenericStub::PrepareCall( - ClientContext* context, const grpc::string& method, CompletionQueue* cq) { +std::unique_ptr GenericStub::PrepareCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq) { return CallInternal(channel_.get(), context, method, cq, false, nullptr); } // setup a unary call to a named method -std::unique_ptr GenericStub::PrepareUnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer& request, CompletionQueue* cq) { - return std::unique_ptr( - internal::ClientAsyncResponseReaderFactory::Create( - channel_.get(), cq, - internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), - context, request, false)); +std::unique_ptr +GenericStub::PrepareUnaryCall(grpc::ClientContext* context, + const grpc::string& method, + const grpc::ByteBuffer& request, + grpc::CompletionQueue* cq) { + return std::unique_ptr( + grpc::internal::ClientAsyncResponseReaderFactory< + grpc::ByteBuffer>::Create(channel_.get(), cq, + grpc::internal::RpcMethod( + method.c_str(), + grpc::internal::RpcMethod::NORMAL_RPC), + context, request, false)); } void GenericStub::experimental_type::UnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer* request, ByteBuffer* response, - std::function on_completion) { - internal::CallbackUnaryCall( + grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer* request, grpc::ByteBuffer* response, + std::function on_completion) { + grpc::internal::CallbackUnaryCall( stub_->channel_.get(), - internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), + grpc::internal::RpcMethod(method.c_str(), + grpc::internal::RpcMethod::NORMAL_RPC), context, request, response, std::move(on_completion)); } void GenericStub::experimental_type::PrepareBidiStreamingCall( - ClientContext* context, const grpc::string& method, - experimental::ClientBidiReactor* reactor) { - internal::ClientCallbackReaderWriterFactory::Create( - stub_->channel_.get(), - internal::RpcMethod(method.c_str(), internal::RpcMethod::BIDI_STREAMING), - context, reactor); + grpc::ClientContext* context, const grpc::string& method, + grpc::experimental::ClientBidiReactor* + reactor) { + grpc::internal::ClientCallbackReaderWriterFactory< + grpc::ByteBuffer, + grpc::ByteBuffer>::Create(stub_->channel_.get(), + grpc::internal::RpcMethod( + method.c_str(), + grpc::internal::RpcMethod::BIDI_STREAMING), + context, reactor); } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/common/channel_arguments.cc b/src/cpp/common/channel_arguments.cc index 214d72f853f..c3d75054b9b 100644 --- a/src/cpp/common/channel_arguments.cc +++ b/src/cpp/common/channel_arguments.cc @@ -143,7 +143,7 @@ void ChannelArguments::SetUserAgentPrefix( } void ChannelArguments::SetResourceQuota( - const grpc::ResourceQuota& resource_quota) { + const grpc_impl::ResourceQuota& resource_quota) { SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota.c_resource_quota(), grpc_resource_quota_arg_vtable()); diff --git a/src/cpp/common/resource_quota_cc.cc b/src/cpp/common/resource_quota_cc.cc index 276e5f79548..4fab2975d89 100644 --- a/src/cpp/common/resource_quota_cc.cc +++ b/src/cpp/common/resource_quota_cc.cc @@ -19,7 +19,7 @@ #include #include -namespace grpc { +namespace grpc_impl { ResourceQuota::ResourceQuota() : impl_(grpc_resource_quota_create(nullptr)) {} @@ -37,4 +37,4 @@ ResourceQuota& ResourceQuota::SetMaxThreads(int new_max_threads) { grpc_resource_quota_set_max_threads(impl_, new_max_threads); return *this; } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 930ec534fd4..166c2d39b35 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include namespace grpc { -grpc::string Version() { return "1.20.0-dev"; } +grpc::string Version() { return "1.21.0-dev"; } } // namespace grpc diff --git a/src/cpp/ext/filters/census/grpc_plugin.cc b/src/cpp/ext/filters/census/grpc_plugin.cc index f978ed3bf51..c5018f0673a 100644 --- a/src/cpp/ext/filters/census/grpc_plugin.cc +++ b/src/cpp/ext/filters/census/grpc_plugin.cc @@ -30,35 +30,6 @@ namespace grpc { -void RegisterOpenCensusPlugin() { - RegisterChannelFilter( - "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */, - nullptr /* condition function */); - RegisterChannelFilter( - "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */, - nullptr /* condition function */); - - // Access measures to ensure they are initialized. Otherwise, creating a view - // before the first RPC would cause an error. - RpcClientSentBytesPerRpc(); - RpcClientReceivedBytesPerRpc(); - RpcClientRoundtripLatency(); - RpcClientServerLatency(); - RpcClientSentMessagesPerRpc(); - RpcClientReceivedMessagesPerRpc(); - - RpcServerSentBytesPerRpc(); - RpcServerReceivedBytesPerRpc(); - RpcServerServerLatency(); - RpcServerSentMessagesPerRpc(); - RpcServerReceivedMessagesPerRpc(); -} - -::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context) { - return reinterpret_cast(context->census_context()) - ->Span(); -} - // These measure definitions should be kept in sync across opencensus // implementations--see // https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java. @@ -126,5 +97,39 @@ ABSL_CONST_INIT const absl::string_view ABSL_CONST_INIT const absl::string_view kRpcServerServerLatencyMeasureName = "grpc.io/server/server_latency"; - } // namespace grpc +namespace grpc_impl { + +void RegisterOpenCensusPlugin() { + grpc::RegisterChannelFilter( + "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */, + nullptr /* condition function */); + grpc::RegisterChannelFilter( + "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */, + nullptr /* condition function */); + + // Access measures to ensure they are initialized. Otherwise, creating a view + // before the first RPC would cause an error. + grpc::RpcClientSentBytesPerRpc(); + grpc::RpcClientReceivedBytesPerRpc(); + grpc::RpcClientRoundtripLatency(); + grpc::RpcClientServerLatency(); + grpc::RpcClientSentMessagesPerRpc(); + grpc::RpcClientReceivedMessagesPerRpc(); + + grpc::RpcServerSentBytesPerRpc(); + grpc::RpcServerReceivedBytesPerRpc(); + grpc::RpcServerServerLatency(); + grpc::RpcServerSentMessagesPerRpc(); + grpc::RpcServerReceivedMessagesPerRpc(); +} + +::opencensus::trace::Span GetSpanFromServerContext( + grpc::ServerContext* context) { + return reinterpret_cast(context->census_context()) + ->Span(); +} + +} // namespace grpc_impl diff --git a/src/cpp/ext/filters/census/grpc_plugin.h b/src/cpp/ext/filters/census/grpc_plugin.h index 9e319cb994e..993faae0a94 100644 --- a/src/cpp/ext/filters/census/grpc_plugin.h +++ b/src/cpp/ext/filters/census/grpc_plugin.h @@ -26,7 +26,6 @@ #include "opencensus/stats/stats.h" namespace grpc { - class ServerContext; // The tag keys set when recording RPC stats. diff --git a/src/cpp/ext/filters/census/views.cc b/src/cpp/ext/filters/census/views.cc index 2c0c5f72950..d7e3c81a955 100644 --- a/src/cpp/ext/filters/census/views.cc +++ b/src/cpp/ext/filters/census/views.cc @@ -25,6 +25,23 @@ #include "opencensus/stats/internal/set_aggregation_window.h" #include "opencensus/stats/stats.h" +namespace grpc_impl { + +void RegisterOpenCensusViewsForExport() { + grpc::ClientSentMessagesPerRpcCumulative().RegisterForExport(); + grpc::ClientSentBytesPerRpcCumulative().RegisterForExport(); + grpc::ClientReceivedMessagesPerRpcCumulative().RegisterForExport(); + grpc::ClientReceivedBytesPerRpcCumulative().RegisterForExport(); + grpc::ClientRoundtripLatencyCumulative().RegisterForExport(); + grpc::ClientServerLatencyCumulative().RegisterForExport(); + + grpc::ServerSentMessagesPerRpcCumulative().RegisterForExport(); + grpc::ServerSentBytesPerRpcCumulative().RegisterForExport(); + grpc::ServerReceivedMessagesPerRpcCumulative().RegisterForExport(); + grpc::ServerReceivedBytesPerRpcCumulative().RegisterForExport(); + grpc::ServerServerLatencyCumulative().RegisterForExport(); +} +} // namespace grpc_impl namespace grpc { using ::opencensus::stats::Aggregation; @@ -71,21 +88,6 @@ ViewDescriptor HourDescriptor() { } // namespace -void RegisterOpenCensusViewsForExport() { - ClientSentMessagesPerRpcCumulative().RegisterForExport(); - ClientSentBytesPerRpcCumulative().RegisterForExport(); - ClientReceivedMessagesPerRpcCumulative().RegisterForExport(); - ClientReceivedBytesPerRpcCumulative().RegisterForExport(); - ClientRoundtripLatencyCumulative().RegisterForExport(); - ClientServerLatencyCumulative().RegisterForExport(); - - ServerSentMessagesPerRpcCumulative().RegisterForExport(); - ServerSentBytesPerRpcCumulative().RegisterForExport(); - ServerReceivedMessagesPerRpcCumulative().RegisterForExport(); - ServerReceivedBytesPerRpcCumulative().RegisterForExport(); - ServerServerLatencyCumulative().RegisterForExport(); -} - // client cumulative const ViewDescriptor& ClientSentBytesPerRpcCumulative() { const static ViewDescriptor descriptor = diff --git a/src/cpp/ext/proto_server_reflection_plugin.cc b/src/cpp/ext/proto_server_reflection_plugin.cc index ee3ac3fee88..0ac4cb80c64 100644 --- a/src/cpp/ext/proto_server_reflection_plugin.cc +++ b/src/cpp/ext/proto_server_reflection_plugin.cc @@ -23,7 +23,7 @@ #include "src/cpp/ext/proto_server_reflection.h" -namespace grpc { +namespace grpc_impl { namespace reflection { ProtoServerReflectionPlugin::ProtoServerReflectionPlugin() @@ -79,4 +79,4 @@ struct StaticProtoReflectionPluginInitializer { } static_proto_reflection_plugin_initializer; } // namespace reflection -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/channelz/channelz_service.cc b/src/cpp/server/channelz/channelz_service.cc index c44a9ac0de6..0409991fe67 100644 --- a/src/cpp/server/channelz/channelz_service.cc +++ b/src/cpp/server/channelz/channelz_service.cc @@ -24,6 +24,12 @@ #include namespace grpc { +grpc::protobuf::util::Status ParseJson(const char* json_str, + grpc::protobuf::Message* message) { + grpc::protobuf::json::JsonParseOptions options; + options.case_insensitive_enum_parsing = true; + return grpc::protobuf::json::JsonStringToMessage(json_str, message, options); +} Status ChannelzService::GetTopChannels( ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request, @@ -33,8 +39,7 @@ Status ChannelzService::GetTopChannels( return Status(StatusCode::INTERNAL, "grpc_channelz_get_top_channels returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -50,8 +55,7 @@ Status ChannelzService::GetServers( return Status(StatusCode::INTERNAL, "grpc_channelz_get_servers returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -67,8 +71,7 @@ Status ChannelzService::GetServer(ServerContext* unused, return Status(StatusCode::INTERNAL, "grpc_channelz_get_server returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -85,8 +88,7 @@ Status ChannelzService::GetServerSockets( return Status(StatusCode::INTERNAL, "grpc_channelz_get_server_sockets returned null"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -101,8 +103,7 @@ Status ChannelzService::GetChannel( if (json_str == nullptr) { return Status(StatusCode::NOT_FOUND, "No object found for that ChannelId"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -118,8 +119,7 @@ Status ChannelzService::GetSubchannel( return Status(StatusCode::NOT_FOUND, "No object found for that SubchannelId"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); @@ -134,8 +134,7 @@ Status ChannelzService::GetSocket(ServerContext* unused, if (json_str == nullptr) { return Status(StatusCode::NOT_FOUND, "No object found for that SocketId"); } - grpc::protobuf::util::Status s = - grpc::protobuf::json::JsonStringToMessage(json_str, response); + grpc::protobuf::util::Status s = ParseJson(json_str, response); gpr_free(json_str); if (!s.ok()) { return Status(StatusCode::INTERNAL, s.ToString()); diff --git a/src/cpp/server/channelz/channelz_service_plugin.cc b/src/cpp/server/channelz/channelz_service_plugin.cc index b93e5b551e1..04c6411d5a3 100644 --- a/src/cpp/server/channelz/channelz_service_plugin.cc +++ b/src/cpp/server/channelz/channelz_service_plugin.cc @@ -67,13 +67,21 @@ CreateChannelzServicePlugin() { new ChannelzServicePlugin()); } +} // namespace experimental +} // namespace channelz +} // namespace grpc +namespace grpc_impl { +namespace channelz { +namespace experimental { + void InitChannelzService() { static bool already_here = false; if (already_here) return; already_here = true; - ::grpc::ServerBuilder::InternalAddPluginFactory(&CreateChannelzServicePlugin); + ::grpc::ServerBuilder::InternalAddPluginFactory( + &grpc::channelz::experimental::CreateChannelzServicePlugin); } } // namespace experimental } // namespace channelz -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/health/health_check_service.cc b/src/cpp/server/health/health_check_service.cc index a0fa2d62f58..ca0b49a1ae8 100644 --- a/src/cpp/server/health/health_check_service.cc +++ b/src/cpp/server/health/health_check_service.cc @@ -16,9 +16,9 @@ * */ -#include +#include -namespace grpc { +namespace grpc_impl { namespace { bool g_grpc_default_health_check_service_enabled = false; } // namespace @@ -31,4 +31,4 @@ void EnableDefaultHealthCheckService(bool enable) { g_grpc_default_health_check_service_enabled = enable; } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 7d749ddca4d..e4623ececef 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -21,7 +21,7 @@ #include #include -namespace grpc { +namespace grpc_impl { namespace { class InsecureServerCredentialsImpl final : public ServerCredentials { public: @@ -29,7 +29,7 @@ class InsecureServerCredentialsImpl final : public ServerCredentials { return grpc_server_add_insecure_http2_port(server, addr.c_str()); } void SetAuthMetadataProcessor( - const std::shared_ptr& processor) override { + const std::shared_ptr& processor) override { (void)processor; GPR_ASSERT(0); // Should not be called on InsecureServerCredentials. } @@ -41,4 +41,4 @@ std::shared_ptr InsecureServerCredentials() { new InsecureServerCredentialsImpl()); } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc b/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc index 81cf6ac562d..ab63bebb792 100644 --- a/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc +++ b/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc @@ -22,7 +22,7 @@ #include "src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h" -namespace grpc { +namespace grpc_impl { namespace load_reporter { namespace experimental { @@ -33,9 +33,10 @@ void LoadReportingServiceServerBuilderOption::UpdateArguments( void LoadReportingServiceServerBuilderOption::UpdatePlugins( std::vector>* plugins) { - plugins->emplace_back(new LoadReportingServiceServerBuilderPlugin()); + plugins->emplace_back( + new grpc::load_reporter::LoadReportingServiceServerBuilderPlugin()); } } // namespace experimental } // namespace load_reporter -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h b/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h index 1f098591d4d..c80802b2638 100644 --- a/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h +++ b/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h @@ -36,13 +36,13 @@ class LoadReportingServiceServerBuilderPlugin : public ServerBuilderPlugin { grpc::string name() override { return "load_reporting_service"; } // Creates a load reporting service. - void UpdateServerBuilder(grpc::ServerBuilder* builder) override; + void UpdateServerBuilder(ServerBuilder* builder) override; // Registers the load reporter service. - void InitServer(grpc::ServerInitializer* si) override; + void InitServer(grpc_impl::ServerInitializer* si) override; // Starts the load reporter service. - void Finish(grpc::ServerInitializer* si) override; + void Finish(grpc_impl::ServerInitializer* si) override; void ChangeArguments(const grpc::string& name, void* value) override {} void UpdateChannelArguments(grpc::ChannelArguments* args) override {} diff --git a/src/cpp/server/load_reporter/util.cc b/src/cpp/server/load_reporter/util.cc index 89bdf57049c..b69705a6994 100644 --- a/src/cpp/server/load_reporter/util.cc +++ b/src/cpp/server/load_reporter/util.cc @@ -24,7 +24,7 @@ #include -namespace grpc { +namespace grpc_impl { namespace load_reporter { namespace experimental { @@ -44,4 +44,4 @@ void AddLoadReportingCost(grpc::ServerContext* ctx, } // namespace experimental } // namespace load_reporter -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 453e76eb25d..93dc10f14ea 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -93,21 +93,25 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor( status.error_message().c_str()); } +} // namespace grpc + +namespace grpc_impl { + int SecureServerCredentials::AddPortToServer(const grpc::string& addr, grpc_server* server) { return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_); } void SecureServerCredentials::SetAuthMetadataProcessor( - const std::shared_ptr& processor) { - auto* wrapper = new AuthMetadataProcessorAyncWrapper(processor); + const std::shared_ptr& processor) { + auto* wrapper = new grpc::AuthMetadataProcessorAyncWrapper(processor); grpc_server_credentials_set_auth_metadata_processor( - creds_, {AuthMetadataProcessorAyncWrapper::Process, - AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); + creds_, {grpc::AuthMetadataProcessorAyncWrapper::Process, + grpc::AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); } std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options) { + const grpc::SslServerCredentialsOptions& options) { std::vector pem_key_cert_pairs; for (auto key_cert_pair = options.pem_key_cert_pairs.begin(); key_cert_pair != options.pem_key_cert_pairs.end(); key_cert_pair++) { @@ -147,4 +151,4 @@ std::shared_ptr LocalServerCredentials( } } // namespace experimental -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index 8a81af2f591..24b133cf7f0 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -27,8 +27,15 @@ #include "src/cpp/server/thread_pool_interface.h" +namespace grpc_impl { + +class SecureServerCredentials; +} // namespace grpc_impl + namespace grpc { +typedef ::grpc_impl::SecureServerCredentials SecureServerCredentials; + class AuthMetadataProcessorAyncWrapper final { public: static void Destroy(void* wrapper); @@ -49,6 +56,10 @@ class AuthMetadataProcessorAyncWrapper final { std::shared_ptr processor_; }; +} // namespace grpc + +namespace grpc_impl { + class SecureServerCredentials final : public ServerCredentials { public: explicit SecureServerCredentials(grpc_server_credentials* creds) @@ -60,13 +71,13 @@ class SecureServerCredentials final : public ServerCredentials { int AddPortToServer(const grpc::string& addr, grpc_server* server) override; void SetAuthMetadataProcessor( - const std::shared_ptr& processor) override; + const std::shared_ptr& processor) override; private: grpc_server_credentials* creds_; - std::unique_ptr processor_; + std::unique_ptr processor_; }; -} // namespace grpc +} // namespace grpc_impl #endif // GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index cd0e516d9a3..af76ffbe9b5 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -29,15 +29,15 @@ #include "src/core/lib/gpr/useful.h" #include "src/cpp/server/thread_pool_interface.h" -namespace grpc { +namespace grpc_impl { -static std::vector (*)()>* +static std::vector (*)()>* g_plugin_factory_list; static gpr_once once_init_plugin_list = GPR_ONCE_INIT; static void do_plugin_list_init(void) { g_plugin_factory_list = - new std::vector (*)()>(); + new std::vector (*)()>(); } ServerBuilder::ServerBuilder() @@ -67,29 +67,29 @@ ServerBuilder::~ServerBuilder() { } } -std::unique_ptr ServerBuilder::AddCompletionQueue( +std::unique_ptr ServerBuilder::AddCompletionQueue( bool is_frequently_polled) { - ServerCompletionQueue* cq = new ServerCompletionQueue( + grpc::ServerCompletionQueue* cq = new grpc::ServerCompletionQueue( GRPC_CQ_NEXT, is_frequently_polled ? GRPC_CQ_DEFAULT_POLLING : GRPC_CQ_NON_LISTENING, nullptr); cqs_.push_back(cq); - return std::unique_ptr(cq); + return std::unique_ptr(cq); } -ServerBuilder& ServerBuilder::RegisterService(Service* service) { +ServerBuilder& ServerBuilder::RegisterService(grpc::Service* service) { services_.emplace_back(new NamedService(service)); return *this; } ServerBuilder& ServerBuilder::RegisterService(const grpc::string& addr, - Service* service) { + grpc::Service* service) { services_.emplace_back(new NamedService(addr, service)); return *this; } ServerBuilder& ServerBuilder::RegisterAsyncGenericService( - AsyncGenericService* service) { + grpc::AsyncGenericService* service) { if (generic_service_ || callback_generic_service_) { gpr_log(GPR_ERROR, "Adding multiple generic services is unsupported for now. " @@ -102,7 +102,7 @@ ServerBuilder& ServerBuilder::RegisterAsyncGenericService( } ServerBuilder& ServerBuilder::experimental_type::RegisterCallbackGenericService( - experimental::CallbackGenericService* service) { + grpc::experimental::CallbackGenericService* service) { if (builder_->generic_service_ || builder_->callback_generic_service_) { gpr_log(GPR_ERROR, "Adding multiple generic services is unsupported for now. " @@ -115,7 +115,7 @@ ServerBuilder& ServerBuilder::experimental_type::RegisterCallbackGenericService( } ServerBuilder& ServerBuilder::SetOption( - std::unique_ptr option) { + std::unique_ptr option) { options_.push_back(std::move(option)); return *this; } @@ -164,7 +164,7 @@ ServerBuilder& ServerBuilder::SetDefaultCompressionAlgorithm( } ServerBuilder& ServerBuilder::SetResourceQuota( - const grpc::ResourceQuota& resource_quota) { + const grpc_impl::ResourceQuota& resource_quota) { if (resource_quota_ != nullptr) { grpc_resource_quota_unref(resource_quota_); } @@ -174,8 +174,8 @@ ServerBuilder& ServerBuilder::SetResourceQuota( } ServerBuilder& ServerBuilder::AddListeningPort( - const grpc::string& addr_uri, std::shared_ptr creds, - int* selected_port) { + const grpc::string& addr_uri, + std::shared_ptr creds, int* selected_port) { const grpc::string uri_scheme = "dns:"; grpc::string addr = addr_uri; if (addr_uri.compare(0, uri_scheme.size(), uri_scheme) == 0) { @@ -188,8 +188,8 @@ ServerBuilder& ServerBuilder::AddListeningPort( return *this; } -std::unique_ptr ServerBuilder::BuildAndStart() { - ChannelArguments args; +std::unique_ptr ServerBuilder::BuildAndStart() { + grpc::ChannelArguments args; for (auto option = options_.begin(); option != options_.end(); ++option) { (*option)->UpdateArguments(&args); (*option)->UpdatePlugins(&plugins_); @@ -251,9 +251,10 @@ std::unique_ptr ServerBuilder::BuildAndStart() { // This is different from the completion queues added to the server via // ServerBuilder's AddCompletionQueue() method (those completion queues // are in 'cqs_' member variable of ServerBuilder object) - std::shared_ptr>> - sync_server_cqs(std::make_shared< - std::vector>>()); + std::shared_ptr>> + sync_server_cqs( + std::make_shared< + std::vector>>()); bool has_frequently_polled_cqs = false; for (auto it = cqs_.begin(); it != cqs_.end(); ++it) { @@ -282,7 +283,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { // Create completion queues to listen to incoming rpc requests for (int i = 0; i < sync_server_settings_.num_cqs; i++) { sync_server_cqs->emplace_back( - new ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr)); + new grpc::ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr)); } } @@ -303,13 +304,13 @@ std::unique_ptr ServerBuilder::BuildAndStart() { gpr_log(GPR_INFO, "Callback server."); } - std::unique_ptr server(new Server( + std::unique_ptr server(new grpc::Server( max_receive_message_size_, &args, sync_server_cqs, sync_server_settings_.min_pollers, sync_server_settings_.max_pollers, sync_server_settings_.cq_timeout_msec, resource_quota_, std::move(interceptor_creators_))); - ServerInitializer* initializer = server->initializer(); + grpc_impl::ServerInitializer* initializer = server->initializer(); // Register all the completion queues with the server. i.e // 1. sync_server_cqs: internal completion queues created IF this is a sync @@ -393,7 +394,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { } void ServerBuilder::InternalAddPluginFactory( - std::unique_ptr (*CreatePlugin)()) { + std::unique_ptr (*CreatePlugin)()) { gpr_once_init(&once_init_plugin_list, do_plugin_list_init); (*g_plugin_factory_list).push_back(CreatePlugin); } @@ -408,4 +409,4 @@ ServerBuilder& ServerBuilder::EnableWorkaround(grpc_workaround_list id) { } } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 26e84f1aed4..aa9fdac9bea 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -766,7 +766,7 @@ Server::Server( shutdown_(false), shutdown_notified_(false), server_(nullptr), - server_initializer_(new ServerInitializer(this)), + server_initializer_(new grpc_impl::ServerInitializer(this)), health_check_service_disabled_(false) { g_gli_initializer.summon(); gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks); diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 73fd6a62c48..2bbf0e727a1 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -209,7 +209,11 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { bool call_cancel = (cancelled_ != 0); // If it's a unary cancel callback, call it under the lock so that it doesn't - // race with ClearCancelCallback + // race with ClearCancelCallback. Although we don't normally call callbacks + // under a lock, this is a special case since the user needs a guarantee that + // the callback won't issue or run after ClearCancelCallback has returned. + // This requirement imposes certain restrictions on the callback, documented + // in the API comments of SetCancelCallback. if (cancel_callback_) { cancel_callback_(); } @@ -219,7 +223,7 @@ bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { lock.unlock(); if (call_cancel && reactor_ != nullptr) { - reactor_->OnCancel(); + reactor_->MaybeCallOnCancel(); } /* Add interception point and run through interceptors */ diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc index c3b3a8b3793..8b85264f9d7 100644 --- a/src/cpp/server/server_credentials.cc +++ b/src/cpp/server/server_credentials.cc @@ -16,10 +16,10 @@ * */ -#include +#include -namespace grpc { +namespace grpc_impl { ServerCredentials::~ServerCredentials() {} -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/server_posix.cc b/src/cpp/server/server_posix.cc index 7c221ed036a..7b77e24bc0e 100644 --- a/src/cpp/server/server_posix.cc +++ b/src/cpp/server/server_posix.cc @@ -20,14 +20,14 @@ #include -namespace grpc { +namespace grpc_impl { #ifdef GPR_SUPPORT_CHANNELS_FROM_FD -void AddInsecureChannelFromFd(Server* server, int fd) { +void AddInsecureChannelFromFd(grpc::Server* server, int fd) { grpc_server_add_insecure_channel_from_fd(server->c_server(), nullptr, fd); } #endif // GPR_SUPPORT_CHANNELS_FROM_FD -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/util/error_details.cc b/src/cpp/util/error_details.cc index 42c887aed73..a1aafcbdc6e 100644 --- a/src/cpp/util/error_details.cc +++ b/src/cpp/util/error_details.cc @@ -20,29 +20,31 @@ #include "src/proto/grpc/status/status.pb.h" -namespace grpc { +namespace grpc_impl { -Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to) { +grpc::Status ExtractErrorDetails(const grpc::Status& from, + ::google::rpc::Status* to) { if (to == nullptr) { - return Status(StatusCode::FAILED_PRECONDITION, ""); + return grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, ""); } if (!to->ParseFromString(from.error_details())) { - return Status(StatusCode::INVALID_ARGUMENT, ""); + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, ""); } - return Status::OK; + return grpc::Status::OK; } -Status SetErrorDetails(const ::google::rpc::Status& from, Status* to) { +grpc::Status SetErrorDetails(const ::google::rpc::Status& from, + grpc::Status* to) { if (to == nullptr) { - return Status(StatusCode::FAILED_PRECONDITION, ""); + return grpc::Status(grpc::StatusCode::FAILED_PRECONDITION, ""); } - StatusCode code = StatusCode::UNKNOWN; - if (from.code() >= StatusCode::OK && - from.code() <= StatusCode::UNAUTHENTICATED) { - code = static_cast(from.code()); + grpc::StatusCode code = grpc::StatusCode::UNKNOWN; + if (from.code() >= grpc::StatusCode::OK && + from.code() <= grpc::StatusCode::UNAUTHENTICATED) { + code = static_cast(from.code()); } - *to = Status(code, from.message(), from.SerializeAsString()); - return Status::OK; + *to = grpc::Status(code, from.message(), from.SerializeAsString()); + return grpc::Status::OK; } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/csharp/Grpc.Core/AsyncAuthInterceptor.cs b/src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncAuthInterceptor.cs rename to src/csharp/Grpc.Core.Api/AsyncAuthInterceptor.cs diff --git a/src/csharp/Grpc.Core/AsyncClientStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncClientStreamingCall.cs rename to src/csharp/Grpc.Core.Api/AsyncClientStreamingCall.cs diff --git a/src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncDuplexStreamingCall.cs rename to src/csharp/Grpc.Core.Api/AsyncDuplexStreamingCall.cs diff --git a/src/csharp/Grpc.Core/AsyncServerStreamingCall.cs b/src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncServerStreamingCall.cs rename to src/csharp/Grpc.Core.Api/AsyncServerStreamingCall.cs diff --git a/src/csharp/Grpc.Core/AsyncUnaryCall.cs b/src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs similarity index 100% rename from src/csharp/Grpc.Core/AsyncUnaryCall.cs rename to src/csharp/Grpc.Core.Api/AsyncUnaryCall.cs diff --git a/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs new file mode 100644 index 00000000000..2ee0abe1d0a --- /dev/null +++ b/src/csharp/Grpc.Core.Api/BindServiceMethodAttribute.cs @@ -0,0 +1,53 @@ +#region Copyright notice and license +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +using System; + +namespace Grpc.Core +{ + /// + /// Specifies the location of the service bind method for a gRPC service. + /// The bind method is typically generated code and is used to register a service's + /// methods with the server on startup. + /// + /// The bind method signature takes a and an optional + /// instance of the service base class, e.g. static void BindService(ServiceBinderBase, GreeterService). + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public class BindServiceMethodAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The type the service bind method is defined on. + /// The name of the service bind method. + public BindServiceMethodAttribute(Type bindType, string bindMethodName) + { + BindType = bindType; + BindMethodName = bindMethodName; + } + + /// + /// Gets the type the service bind method is defined on. + /// + public Type BindType { get; } + + /// + /// Gets the name of the service bind method. + /// + public string BindMethodName { get; } + } +} diff --git a/src/csharp/Grpc.Core.Api/CallCredentials.cs b/src/csharp/Grpc.Core.Api/CallCredentials.cs new file mode 100644 index 00000000000..6344a881070 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallCredentials.cs @@ -0,0 +1,90 @@ +#region Copyright notice and license + +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + /// + /// Client-side call credentials. Provide authorization with per-call granularity. + /// + public abstract class CallCredentials + { + /// + /// Composes multiple multiple CallCredentials objects into + /// a single CallCredentials object. + /// + /// credentials to compose + /// The new CompositeCallCredentials + public static CallCredentials Compose(params CallCredentials[] credentials) + { + return new CompositeCallCredentials(credentials); + } + + /// + /// Creates a new instance of CallCredentials class from an + /// interceptor that can attach metadata to outgoing calls. + /// + /// authentication interceptor + public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) + { + return new AsyncAuthInterceptorCredentials(interceptor); + } + + /// + /// Populates this call credential instances. + /// You never need to invoke this, part of internal implementation. + /// + public abstract void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state); + + private class CompositeCallCredentials : CallCredentials + { + readonly IReadOnlyList credentials; + + public CompositeCallCredentials(CallCredentials[] credentials) + { + GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); + this.credentials = new List(credentials).AsReadOnly(); + } + + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + configurator.SetCompositeCredentials(state, credentials); + } + } + + private class AsyncAuthInterceptorCredentials : CallCredentials + { + readonly AsyncAuthInterceptor interceptor; + + public AsyncAuthInterceptorCredentials(AsyncAuthInterceptor interceptor) + { + this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); + } + + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) + { + configurator.SetAsyncAuthInterceptorCredentials(state, interceptor); + } + } + } +} diff --git a/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs b/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs new file mode 100644 index 00000000000..51f8d729a11 --- /dev/null +++ b/src/csharp/Grpc.Core.Api/CallCredentialsConfiguratorBase.cs @@ -0,0 +1,39 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System.Collections.Generic; + +namespace Grpc.Core +{ + /// + /// Base class for objects that can consume configuration from CallCredentials objects. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public abstract class CallCredentialsConfiguratorBase + { + /// + /// Consumes configuration for composite call credentials. + /// + public abstract void SetCompositeCredentials(object state, IReadOnlyList credentials); + + /// + /// Consumes configuration for call credentials created from AsyncAuthInterceptor + /// + public abstract void SetAsyncAuthInterceptorCredentials(object state, AsyncAuthInterceptor interceptor); + } +} diff --git a/src/csharp/Grpc.Core/Internal/CallFlags.cs b/src/csharp/Grpc.Core.Api/CallFlags.cs similarity index 100% rename from src/csharp/Grpc.Core/Internal/CallFlags.cs rename to src/csharp/Grpc.Core.Api/CallFlags.cs diff --git a/src/csharp/Grpc.Core/CallInvoker.cs b/src/csharp/Grpc.Core.Api/CallInvoker.cs similarity index 98% rename from src/csharp/Grpc.Core/CallInvoker.cs rename to src/csharp/Grpc.Core.Api/CallInvoker.cs index 09fbf0b1e8d..8a84a5215ce 100644 --- a/src/csharp/Grpc.Core/CallInvoker.cs +++ b/src/csharp/Grpc.Core.Api/CallInvoker.cs @@ -17,14 +17,12 @@ #endregion using System.Threading.Tasks; -using Grpc.Core.Internal; namespace Grpc.Core { /// /// Abstraction of client-side RPC invocation. /// - /// public abstract class CallInvoker { /// diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core.Api/CallOptions.cs similarity index 84% rename from src/csharp/Grpc.Core/CallOptions.cs rename to src/csharp/Grpc.Core.Api/CallOptions.cs index a92caae917d..c0b732a1005 100644 --- a/src/csharp/Grpc.Core/CallOptions.cs +++ b/src/csharp/Grpc.Core.Api/CallOptions.cs @@ -20,7 +20,6 @@ using System; using System.Threading; using Grpc.Core.Internal; -using Grpc.Core.Utils; namespace Grpc.Core { @@ -227,36 +226,5 @@ namespace Grpc.Core newOptions.flags = flags; return newOptions; } - - /// - /// Returns a new instance of with - /// all previously unset values set to their defaults and deadline and cancellation - /// token propagated when appropriate. - /// - internal CallOptions Normalize() - { - var newOptions = this; - // silently ignore the context propagation token if it wasn't produced by "us" - var propagationTokenImpl = propagationToken.AsImplOrNull(); - if (propagationTokenImpl != null) - { - if (propagationTokenImpl.Options.IsPropagateDeadline) - { - GrpcPreconditions.CheckArgument(!newOptions.deadline.HasValue, - "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); - newOptions.deadline = propagationTokenImpl.ParentDeadline; - } - if (propagationTokenImpl.Options.IsPropagateCancellation) - { - GrpcPreconditions.CheckArgument(!newOptions.cancellationToken.CanBeCanceled, - "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); - newOptions.cancellationToken = propagationTokenImpl.ParentCancellationToken; - } - } - - newOptions.headers = newOptions.headers ?? Metadata.Empty; - newOptions.deadline = newOptions.deadline ?? DateTime.MaxValue; - return newOptions; - } } } diff --git a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj index 1d8632a1df7..6c29530402c 100755 --- a/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj +++ b/src/csharp/Grpc.Core.Api/Grpc.Core.Api.csproj @@ -21,10 +21,6 @@ - - - - diff --git a/src/csharp/Grpc.Core/IClientStreamWriter.cs b/src/csharp/Grpc.Core.Api/IClientStreamWriter.cs similarity index 100% rename from src/csharp/Grpc.Core/IClientStreamWriter.cs rename to src/csharp/Grpc.Core.Api/IClientStreamWriter.cs diff --git a/src/csharp/Grpc.Core.Api/VersionInfo.cs b/src/csharp/Grpc.Core.Api/VersionInfo.cs index 10efb17a678..1b2602e219d 100644 --- a/src/csharp/Grpc.Core.Api/VersionInfo.cs +++ b/src/csharp/Grpc.Core.Api/VersionInfo.cs @@ -33,11 +33,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "1.20.0.0"; + public const string CurrentAssemblyFileVersion = "1.21.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "1.20.0-dev"; + public const string CurrentVersion = "1.21.0-dev"; } } diff --git a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs index f23c9e97574..59587b9a510 100644 --- a/src/csharp/Grpc.Core.Tests/FakeCredentials.cs +++ b/src/csharp/Grpc.Core.Tests/FakeCredentials.cs @@ -42,9 +42,9 @@ namespace Grpc.Core.Tests internal class FakeCallCredentials : CallCredentials { - internal override CallCredentialsSafeHandle ToNativeCredentials() + public override void InternalPopulateConfiguration(CallCredentialsConfiguratorBase configurator, object state) { - return null; + // not invoking the configurator on purpose } } } diff --git a/src/csharp/Grpc.Core/CallCredentials.cs b/src/csharp/Grpc.Core/CallCredentials.cs deleted file mode 100644 index c1bd95b9e22..00000000000 --- a/src/csharp/Grpc.Core/CallCredentials.cs +++ /dev/null @@ -1,129 +0,0 @@ -#region Copyright notice and license - -// Copyright 2015 gRPC authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#endregion - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -using Grpc.Core.Internal; -using Grpc.Core.Utils; - -namespace Grpc.Core -{ - /// - /// Client-side call credentials. Provide authorization with per-call granularity. - /// - public abstract class CallCredentials - { - /// - /// Composes multiple multiple CallCredentials objects into - /// a single CallCredentials object. - /// - /// credentials to compose - /// The new CompositeCallCredentials - public static CallCredentials Compose(params CallCredentials[] credentials) - { - return new CompositeCallCredentials(credentials); - } - - /// - /// Creates a new instance of CallCredentials class from an - /// interceptor that can attach metadata to outgoing calls. - /// - /// authentication interceptor - public static CallCredentials FromInterceptor(AsyncAuthInterceptor interceptor) - { - return new MetadataCredentials(interceptor); - } - - /// - /// Creates native object for the credentials. - /// - /// The native credentials. - internal abstract CallCredentialsSafeHandle ToNativeCredentials(); - } - - /// - /// Client-side credentials that delegate metadata based auth to an interceptor. - /// The interceptor is automatically invoked for each remote call that uses MetadataCredentials. - /// - internal sealed class MetadataCredentials : CallCredentials - { - readonly AsyncAuthInterceptor interceptor; - - /// - /// Initializes a new instance of MetadataCredentials class. - /// - /// authentication interceptor - public MetadataCredentials(AsyncAuthInterceptor interceptor) - { - this.interceptor = GrpcPreconditions.CheckNotNull(interceptor); - } - - internal override CallCredentialsSafeHandle ToNativeCredentials() - { - NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor); - return plugin.Credentials; - } - } - - /// - /// Credentials that allow composing multiple credentials objects into one object. - /// - internal sealed class CompositeCallCredentials : CallCredentials - { - readonly List credentials; - - /// - /// Initializes a new instance of CompositeCallCredentials class. - /// The resulting credentials object will be composite of all the credentials specified as parameters. - /// - /// credentials to compose - public CompositeCallCredentials(params CallCredentials[] credentials) - { - GrpcPreconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials."); - this.credentials = new List(credentials); - } - - internal override CallCredentialsSafeHandle ToNativeCredentials() - { - return ToNativeRecursive(0); - } - - // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. - // In practice, we won't usually see composites from more than two credentials anyway. - private CallCredentialsSafeHandle ToNativeRecursive(int startIndex) - { - if (startIndex == credentials.Count - 1) - { - return credentials[startIndex].ToNativeCredentials(); - } - - using (var cred1 = credentials[startIndex].ToNativeCredentials()) - using (var cred2 = ToNativeRecursive(startIndex + 1)) - { - var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); - if (nativeComposite.IsInvalid) - { - throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); - } - return nativeComposite; - } - } - } -} diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index 7ce929dfa31..97f79b0fb4f 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -59,7 +59,7 @@ namespace Grpc.Core /// /// Creates a channel that connects to a specific host. - /// Port will default to 80 for an unsecure channel and to 443 for a secure channel. + /// Port will default to 80 for an unsecure channel or to 443 for a secure channel. /// /// Target of the channel. /// Credentials to secure the channel. @@ -112,7 +112,7 @@ namespace Grpc.Core /// /// Gets current connectivity state of this channel. - /// After channel is has been shutdown, ChannelState.Shutdown will be returned. + /// After channel has been shutdown, ChannelState.Shutdown will be returned. /// public ChannelState State { @@ -132,7 +132,7 @@ namespace Grpc.Core /// /// Returned tasks completes once channel state has become different from /// given lastObservedState. - /// If deadline is reached or and error occurs, returned task is cancelled. + /// If deadline is reached or an error occurs, returned task is cancelled. /// public async Task WaitForStateChangedAsync(ChannelState lastObservedState, DateTime? deadline = null) { diff --git a/src/csharp/Grpc.Core/ChannelCredentials.cs b/src/csharp/Grpc.Core/ChannelCredentials.cs index 3ce32f31b76..dcbe9f3599b 100644 --- a/src/csharp/Grpc.Core/ChannelCredentials.cs +++ b/src/csharp/Grpc.Core/ChannelCredentials.cs @@ -18,9 +18,11 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Threading.Tasks; using Grpc.Core.Internal; +using Grpc.Core.Logging; using Grpc.Core.Utils; namespace Grpc.Core @@ -104,20 +106,38 @@ namespace Grpc.Core } } + /// + /// Callback invoked with the expected targetHost and the peer's certificate. + /// If false is returned by this callback then it is treated as a + /// verification failure and the attempted connection will fail. + /// Invocation of the callback is blocking, so any + /// implementation should be light-weight. + /// Note that the callback can potentially be invoked multiple times, + /// concurrently from different threads (e.g. when multiple connections + /// are being created for the same credentials). + /// + /// The associated with the callback + /// true if verification succeeded, false otherwise. + /// Note: experimental API that can change or be removed without any prior notice. + public delegate bool VerifyPeerCallback(VerifyPeerContext context); + /// /// Client-side SSL credentials. /// public sealed class SslCredentials : ChannelCredentials { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); + readonly string rootCertificates; readonly KeyCertificatePair keyCertificatePair; + readonly VerifyPeerCallback verifyPeerCallback; /// /// Creates client-side SSL credentials loaded from /// disk file pointed to by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable. /// If that fails, gets the roots certificates from a well known place on disk. /// - public SslCredentials() : this(null, null) + public SslCredentials() : this(null, null, null) { } @@ -125,19 +145,32 @@ namespace Grpc.Core /// Creates client-side SSL credentials from /// a string containing PEM encoded root certificates. /// - public SslCredentials(string rootCertificates) : this(rootCertificates, null) + public SslCredentials(string rootCertificates) : this(rootCertificates, null, null) + { + } + + /// + /// Creates client-side SSL credentials. + /// + /// string containing PEM encoded server root certificates. + /// a key certificate pair. + public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) : + this(rootCertificates, keyCertificatePair, null) { } - + /// /// Creates client-side SSL credentials. /// /// string containing PEM encoded server root certificates. /// a key certificate pair. - public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) + /// a callback to verify peer's target name and certificate. + /// Note: experimental API that can change or be removed without any prior notice. + public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback) { this.rootCertificates = rootCertificates; this.keyCertificatePair = keyCertificatePair; + this.verifyPeerCallback = verifyPeerCallback; } /// @@ -171,7 +204,54 @@ namespace Grpc.Core internal override ChannelCredentialsSafeHandle CreateNativeCredentials() { - return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair); + IntPtr verifyPeerCallbackTag = IntPtr.Zero; + if (verifyPeerCallback != null) + { + verifyPeerCallbackTag = new VerifyPeerCallbackRegistration(verifyPeerCallback).CallbackRegistration.Tag; + } + return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair, verifyPeerCallbackTag); + } + + private class VerifyPeerCallbackRegistration + { + readonly VerifyPeerCallback verifyPeerCallback; + readonly NativeCallbackRegistration callbackRegistration; + + public VerifyPeerCallbackRegistration(VerifyPeerCallback verifyPeerCallback) + { + this.verifyPeerCallback = verifyPeerCallback; + this.callbackRegistration = NativeCallbackDispatcher.RegisterCallback(HandleUniversalCallback); + } + + public NativeCallbackRegistration CallbackRegistration => callbackRegistration; + + private int HandleUniversalCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5) + { + return VerifyPeerCallbackHandler(arg0, arg1, arg2 != IntPtr.Zero); + } + + private int VerifyPeerCallbackHandler(IntPtr targetName, IntPtr peerPem, bool isDestroy) + { + if (isDestroy) + { + this.callbackRegistration.Dispose(); + return 0; + } + + try + { + var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(targetName), Marshal.PtrToStringAnsi(peerPem)); + + return this.verifyPeerCallback(context) ? 0 : 1; + } + catch (Exception e) + { + // eat the exception, we must not throw when inside callback from native code. + Logger.Error(e, "Exception occurred while invoking verify peer callback handler."); + // Return validation failure in case of exception. + return 1; + } + } } } diff --git a/src/csharp/Grpc.Core/ForwardedTypes.cs b/src/csharp/Grpc.Core/ForwardedTypes.cs index 39221925392..3df44d167be 100644 --- a/src/csharp/Grpc.Core/ForwardedTypes.cs +++ b/src/csharp/Grpc.Core/ForwardedTypes.cs @@ -18,21 +18,30 @@ using System.Runtime.CompilerServices; using Grpc.Core; -using Grpc.Core.Logging; +using Grpc.Core.Internal; using Grpc.Core.Utils; // API types that used to be in Grpc.Core package, but were moved to Grpc.Core.Api // https://docs.microsoft.com/en-us/dotnet/framework/app-domains/type-forwarding-in-the-common-language-runtime -// TODO(jtattermusch): move types needed for implementing a client - [assembly:TypeForwardedToAttribute(typeof(GrpcPreconditions))] +[assembly:TypeForwardedToAttribute(typeof(AsyncClientStreamingCall<,>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncDuplexStreamingCall<,>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncServerStreamingCall<>))] +[assembly:TypeForwardedToAttribute(typeof(AsyncUnaryCall<>))] [assembly:TypeForwardedToAttribute(typeof(AuthContext))] +[assembly:TypeForwardedToAttribute(typeof(AsyncAuthInterceptor))] +[assembly:TypeForwardedToAttribute(typeof(AuthInterceptorContext))] +[assembly: TypeForwardedToAttribute(typeof(CallCredentials))] +[assembly: TypeForwardedToAttribute(typeof(CallFlags))] +[assembly: TypeForwardedToAttribute(typeof(CallInvoker))] +[assembly: TypeForwardedToAttribute(typeof(CallOptions))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationOptions))] [assembly:TypeForwardedToAttribute(typeof(ContextPropagationToken))] [assembly:TypeForwardedToAttribute(typeof(DeserializationContext))] [assembly:TypeForwardedToAttribute(typeof(IAsyncStreamReader<>))] [assembly:TypeForwardedToAttribute(typeof(IAsyncStreamWriter<>))] +[assembly:TypeForwardedToAttribute(typeof(IClientStreamWriter<>))] [assembly:TypeForwardedToAttribute(typeof(IServerStreamWriter<>))] [assembly:TypeForwardedToAttribute(typeof(Marshaller<>))] [assembly:TypeForwardedToAttribute(typeof(Marshallers))] diff --git a/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs b/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs new file mode 100644 index 00000000000..b58b041297f --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CallOptionsExtensions.cs @@ -0,0 +1,57 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + internal static class CallOptionsExtensions + { + /// + /// Returns a new instance of with + /// all previously unset values set to their defaults and deadline and cancellation + /// token propagated when appropriate. + /// + internal static CallOptions Normalize(this CallOptions options) + { + var newOptions = options; + // silently ignore the context propagation token if it wasn't produced by "us" + var propagationTokenImpl = options.PropagationToken.AsImplOrNull(); + if (propagationTokenImpl != null) + { + if (propagationTokenImpl.Options.IsPropagateDeadline) + { + GrpcPreconditions.CheckArgument(!newOptions.Deadline.HasValue, + "Cannot propagate deadline from parent call. The deadline has already been set explicitly."); + newOptions = newOptions.WithDeadline(propagationTokenImpl.ParentDeadline); + } + if (propagationTokenImpl.Options.IsPropagateCancellation) + { + GrpcPreconditions.CheckArgument(!newOptions.CancellationToken.CanBeCanceled, + "Cannot propagate cancellation token from parent call. The cancellation token has already been set to a non-default value."); + newOptions = newOptions.WithCancellationToken(propagationTokenImpl.ParentCancellationToken); + } + } + + newOptions = newOptions.WithHeaders(newOptions.Headers ?? Metadata.Empty); + newOptions = newOptions.WithDeadline(newOptions.Deadline ?? DateTime.MaxValue); + return newOptions; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs index 11b5d2cc3f6..d4f50344b23 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs @@ -38,15 +38,15 @@ namespace Grpc.Core.Internal return creds; } - public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair) + public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, KeyCertificatePair keyCertPair, IntPtr verifyPeerCallbackTag) { if (keyCertPair != null) { - return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey, verifyPeerCallbackTag); } else { - return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null, verifyPeerCallbackTag); } } diff --git a/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs b/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs new file mode 100644 index 00000000000..a2c53a173c5 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultCallCredentialsConfigurator.cs @@ -0,0 +1,85 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using System.Collections.Generic; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// + /// Creates native call credential objects from instances of CallCredentials. + /// + internal class DefaultCallCredentialsConfigurator : CallCredentialsConfiguratorBase + { + CallCredentialsSafeHandle nativeCredentials; + + public CallCredentialsSafeHandle NativeCredentials => nativeCredentials; + + public override void SetAsyncAuthInterceptorCredentials(object state, AsyncAuthInterceptor interceptor) + { + GrpcPreconditions.CheckState(nativeCredentials == null); + + var plugin = new NativeMetadataCredentialsPlugin(interceptor); + nativeCredentials = plugin.Credentials; + } + + public override void SetCompositeCredentials(object state, IReadOnlyList credentials) + { + GrpcPreconditions.CheckState(nativeCredentials == null); + + GrpcPreconditions.CheckArgument(credentials.Count >= 2); + nativeCredentials = CompositeToNativeRecursive(credentials, 0); + } + + // Recursive descent makes managing lifetime of intermediate CredentialSafeHandle instances easier. + // In practice, we won't usually see composites from more than two credentials anyway. + private CallCredentialsSafeHandle CompositeToNativeRecursive(IReadOnlyList credentials, int startIndex) + { + if (startIndex == credentials.Count - 1) + { + return credentials[startIndex].ToNativeCredentials(); + } + + using (var cred1 = credentials[startIndex].ToNativeCredentials()) + using (var cred2 = CompositeToNativeRecursive(credentials, startIndex + 1)) + { + var nativeComposite = CallCredentialsSafeHandle.CreateComposite(cred1, cred2); + if (nativeComposite.IsInvalid) + { + throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials."); + } + return nativeComposite; + } + } + } + + internal static class CallCredentialsExtensions + { + /// + /// Creates native object for the credentials. + /// + /// The native credentials. + public static CallCredentialsSafeHandle ToNativeCredentials(this CallCredentials credentials) + { + var configurator = new DefaultCallCredentialsConfigurator(); + credentials.InternalPopulateConfiguration(configurator, credentials); + return configurator.NativeCredentials; + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs b/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs index d5146e816e2..0777d7933e6 100644 --- a/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs +++ b/src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs @@ -63,7 +63,7 @@ namespace Grpc.Core.Internal catch (Exception e) { // eat the exception, we must not throw when inside callback from native code. - Logger.Error(e, "Caught exception inside callback from native callback."); + Logger.Error(e, "Caught exception inside callback from native code."); return 0; } } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs index b7b9a12d8a3..a1387aff562 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs @@ -482,7 +482,7 @@ namespace Grpc.Core.Internal public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); public delegate void grpcsharp_override_default_ssl_roots_delegate(string pemRootCerts); - public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs); @@ -676,7 +676,7 @@ namespace Grpc.Core.Internal public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); [DllImport(ImportName)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); [DllImport(ImportName)] public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); @@ -972,7 +972,7 @@ namespace Grpc.Core.Internal public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); [DllImport(ImportName)] - public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); [DllImport(ImportName)] public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); diff --git a/src/csharp/Grpc.Core/VerifyPeerContext.cs b/src/csharp/Grpc.Core/VerifyPeerContext.cs new file mode 100644 index 00000000000..b1dc60f8e27 --- /dev/null +++ b/src/csharp/Grpc.Core/VerifyPeerContext.cs @@ -0,0 +1,48 @@ +#region Copyright notice and license + +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +namespace Grpc.Core +{ + /// + /// Verification context for VerifyPeerCallback. + /// Note: experimental API that can change or be removed without any prior notice. + /// + public class VerifyPeerContext + { + /// + /// Initializes a new instance of the class. + /// + /// The target name of the peer. + /// The PEM encoded certificate of the peer. + internal VerifyPeerContext(string targetName, string peerPem) + { + this.TargetName = targetName; + this.PeerPem = peerPem; + } + + /// + /// The target name of the peer. + /// + public string TargetName { get; } + + /// + /// The PEM encoded certificate of the peer. + /// + public string PeerPem { get; } + } +} diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index ba6824dd8e2..fab64354411 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -67,6 +67,7 @@ namespace Math { } /// Base class for server-side implementations of Math + [grpc::BindServiceMethod(typeof(Math), "BindService")] public abstract partial class MathBase { /// diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 3edec5a37f8..7137b907274 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -54,6 +54,7 @@ namespace Grpc.Health.V1 { } /// Base class for server-side implementations of Health + [grpc::BindServiceMethod(typeof(Health), "BindService")] public abstract partial class HealthBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs index 09691d28716..5b37b144f2a 100644 --- a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs @@ -74,6 +74,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of BenchmarkService + [grpc::BindServiceMethod(typeof(BenchmarkService), "BindService")] public abstract partial class BenchmarkServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs index bfa3348f6a0..50c6e159206 100644 --- a/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs @@ -39,6 +39,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of EmptyService + [grpc::BindServiceMethod(typeof(EmptyService), "BindService")] public abstract partial class EmptyServiceBase { } diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs index 27746c07641..9b11e990d2d 100644 --- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs @@ -58,6 +58,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of MetricsService + [grpc::BindServiceMethod(typeof(MetricsService), "BindService")] public abstract partial class MetricsServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs index f92ae8e974b..1a505ebc764 100644 --- a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs @@ -46,6 +46,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of ReportQpsScenarioService + [grpc::BindServiceMethod(typeof(ReportQpsScenarioService), "BindService")] public abstract partial class ReportQpsScenarioServiceBase { /// diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs index b3c47c2d8d3..4c1189320fa 100644 --- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs @@ -46,7 +46,8 @@ namespace Grpc.IntegrationTesting KeyCertificatePair keyCertPair; public void InitClientAndServer(bool clientAddKeyCertPair, - SslClientCertificateRequestType clientCertRequestType) + SslClientCertificateRequestType clientCertRequestType, + VerifyPeerCallback verifyPeerCallback = null) { rootCert = File.ReadAllText(TestCredentials.ClientCertAuthorityPath); keyCertPair = new KeyCertificatePair( @@ -54,7 +55,7 @@ namespace Grpc.IntegrationTesting File.ReadAllText(TestCredentials.ServerPrivateKeyPath)); var serverCredentials = new SslServerCredentials(new[] { keyCertPair }, rootCert, clientCertRequestType); - var clientCredentials = clientAddKeyCertPair ? new SslCredentials(rootCert, keyCertPair) : new SslCredentials(rootCert); + var clientCredentials = new SslCredentials(rootCert, clientAddKeyCertPair ? keyCertPair : null, verifyPeerCallback); // Disable SO_REUSEPORT to prevent https://github.com/grpc/grpc/issues/10755 server = new Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) @@ -188,6 +189,52 @@ namespace Grpc.IntegrationTesting Assert.Throws(typeof(ArgumentNullException), () => new SslServerCredentials(keyCertPairs, null, SslClientCertificateRequestType.RequestAndRequireAndVerify)); } + [Test] + public async Task VerifyPeerCallback_Accepted() + { + string targetNameFromCallback = null; + string peerPemFromCallback = null; + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + targetNameFromCallback = ctx.TargetName; + peerPemFromCallback = ctx.PeerPem; + return true; + }); + await CheckAccepted(expectPeerAuthenticated: false); + Assert.AreEqual(TestCredentials.DefaultHostOverride, targetNameFromCallback); + var expectedServerPem = File.ReadAllText(TestCredentials.ServerCertChainPath).Replace("\r", ""); + Assert.AreEqual(expectedServerPem, peerPemFromCallback); + } + + [Test] + public void VerifyPeerCallback_CallbackThrows_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + throw new Exception("VerifyPeerCallback has thrown on purpose."); + }); + CheckRejected(); + } + + [Test] + public void VerifyPeerCallback_Rejected() + { + InitClientAndServer( + clientAddKeyCertPair: false, + clientCertRequestType: SslClientCertificateRequestType.DontRequest, + verifyPeerCallback: (ctx) => + { + return false; + }); + CheckRejected(); + } + private async Task CheckAccepted(bool expectPeerAuthenticated) { var call = client.UnaryCallAsync(new SimpleRequest { ResponseSize = 10 }); diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index d47b5fe0d4b..e7b93094c65 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -105,6 +105,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of TestService + [grpc::BindServiceMethod(typeof(TestService), "BindService")] public abstract partial class TestServiceBase { /// @@ -580,6 +581,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of UnimplementedService + [grpc::BindServiceMethod(typeof(UnimplementedService), "BindService")] public abstract partial class UnimplementedServiceBase { /// @@ -719,6 +721,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of ReconnectService + [grpc::BindServiceMethod(typeof(ReconnectService), "BindService")] public abstract partial class ReconnectServiceBase { public virtual global::System.Threading.Tasks.Task Start(global::Grpc.Testing.ReconnectParams request, grpc::ServerCallContext context) diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs index f7dd2eecf2e..14c26f99a6b 100644 --- a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs @@ -72,6 +72,7 @@ namespace Grpc.Testing { } /// Base class for server-side implementations of WorkerService + [grpc::BindServiceMethod(typeof(WorkerService), "BindService")] public abstract partial class WorkerServiceBase { /// diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs index 500738205a7..f97b3143a69 100644 --- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs +++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs @@ -46,6 +46,7 @@ namespace Grpc.Reflection.V1Alpha { } /// Base class for server-side implementations of ServerReflection + [grpc::BindServiceMethod(typeof(ServerReflection), "BindService")] public abstract partial class ServerReflectionBase { /// diff --git a/src/csharp/Grpc.Tools/Common.cs b/src/csharp/Grpc.Tools/Common.cs index a4fcfc2c53c..13cd6a32316 100644 --- a/src/csharp/Grpc.Tools/Common.cs +++ b/src/csharp/Grpc.Tools/Common.cs @@ -60,7 +60,7 @@ namespace Grpc.Tools : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OsKind.MacOsX : OsKind.Unknown; - switch (RuntimeInformation.OSArchitecture) + switch (RuntimeInformation.ProcessArchitecture) { case Architecture.X86: Cpu = CpuKind.X86; break; case Architecture.X64: Cpu = CpuKind.X64; break; @@ -86,7 +86,7 @@ namespace Grpc.Tools } // Hope we are not building on ARM under Xamarin! - Cpu = Environment.Is64BitOperatingSystem ? CpuKind.X64 : CpuKind.X86; + Cpu = Environment.Is64BitProcess ? CpuKind.X64 : CpuKind.X86; #endif } }; diff --git a/src/csharp/build/dependencies.props b/src/csharp/build/dependencies.props index f3d484643d7..b018aac0f8e 100644 --- a/src/csharp/build/dependencies.props +++ b/src/csharp/build/dependencies.props @@ -1,7 +1,7 @@ - 1.20.0-dev + 1.21.0-dev 3.7.0 diff --git a/src/csharp/build_unitypackage.bat b/src/csharp/build_unitypackage.bat index 7d403d1338a..8c7718f727f 100644 --- a/src/csharp/build_unitypackage.bat +++ b/src/csharp/build_unitypackage.bat @@ -13,7 +13,7 @@ @rem limitations under the License. @rem Current package versions -set VERSION=1.20.0-dev +set VERSION=1.21.0-dev @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index dc690a6a608..91d3957dbf0 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -901,6 +901,21 @@ grpcsharp_server_request_call(grpc_server* server, grpc_completion_queue* cq, &(ctx->request_metadata), cq, cq, ctx); } +/* Native callback dispatcher */ + +typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)( + void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4, + void* arg5); + +static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher = + NULL; + +GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init( + grpcsharp_native_callback_dispatcher_func func) { + GPR_ASSERT(func); + native_callback_dispatcher = func; +} + /* Security */ static char* default_pem_root_certs = NULL; @@ -927,21 +942,47 @@ grpcsharp_override_default_ssl_roots(const char* pem_root_certs) { grpc_set_ssl_roots_override_callback(override_ssl_roots_handler); } +static void grpcsharp_verify_peer_destroy_handler(void* userdata) { + native_callback_dispatcher(userdata, NULL, NULL, (void*)1, NULL, NULL, NULL); +} + +static int grpcsharp_verify_peer_handler(const char* target_name, + const char* peer_pem, void* userdata) { + return native_callback_dispatcher(userdata, (void*)target_name, + (void*)peer_pem, (void*)0, NULL, NULL, + NULL); +} + GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char* pem_root_certs, const char* key_cert_pair_cert_chain, - const char* key_cert_pair_private_key) { + const char* key_cert_pair_private_key, + void* verify_peer_callback_tag) { grpc_ssl_pem_key_cert_pair key_cert_pair; + verify_peer_options verify_options; + grpc_ssl_pem_key_cert_pair* key_cert_pair_ptr = NULL; + verify_peer_options* verify_options_ptr = NULL; + if (key_cert_pair_cert_chain || key_cert_pair_private_key) { + memset(&key_cert_pair, 0, sizeof(key_cert_pair)); key_cert_pair.cert_chain = key_cert_pair_cert_chain; key_cert_pair.private_key = key_cert_pair_private_key; - return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL, - NULL); + key_cert_pair_ptr = &key_cert_pair; } else { GPR_ASSERT(!key_cert_pair_cert_chain); GPR_ASSERT(!key_cert_pair_private_key); - return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL, NULL); } + + if (verify_peer_callback_tag != NULL) { + memset(&verify_options, 0, sizeof(verify_peer_options)); + verify_options.verify_peer_callback_userdata = verify_peer_callback_tag; + verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler; + verify_options.verify_peer_callback = grpcsharp_verify_peer_handler; + verify_options_ptr = &verify_options; + } + + return grpc_ssl_credentials_create(pem_root_certs, key_cert_pair_ptr, + verify_options_ptr, NULL); } GPR_EXPORT void GPR_CALLTYPE @@ -1010,21 +1051,6 @@ grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1, return grpc_composite_call_credentials_create(creds1, creds2, NULL); } -/* Native callback dispatcher */ - -typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)( - void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4, - void* arg5); - -static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher = - NULL; - -GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init( - grpcsharp_native_callback_dispatcher_func func) { - GPR_ASSERT(func); - native_callback_dispatcher = func; -} - /* Metadata credentials plugin */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin( diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index a318af8f540..af876287038 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.20.0-dev' + v = '1.21.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 74a1b47ba6c..cd3db898985 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -434,6 +434,9 @@ const char *kCFStreamVarName = "grpc_cfstream"; // Guarantees the code in {} block is invoked only once. See ref at: // https://developer.apple.com/documentation/objectivec/nsobject/1418639-initialize?language=objc if (self == [GRPCCall self]) { + // Enable CFStream by default by do not overwrite if the user explicitly disables CFStream with + // environment variable "grpc_cfstream=0" + setenv(kCFStreamVarName, "1", 0); grpc_init(); callFlags = [NSMutableDictionary dictionary]; } diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m index b1a6797b9e3..7557367ed4a 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannelFactory.m @@ -54,10 +54,13 @@ error:(NSError **)errorPtr { static dispatch_once_t loading; dispatch_once(&loading, ^{ - NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem + NSString *rootsPEM = @"roots"; + NSString *resourceBundlePath = @"gRPCCertificates.bundle"; // .pem // Do not use NSBundle.mainBundle, as it's nil for tests of library projects. NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"]; + NSBundle *resourceBundle = [NSBundle + bundleWithURL:[[bundle resourceURL] URLByAppendingPathComponent:resourceBundlePath]]; + NSString *path = [resourceBundle pathForResource:rootsPEM ofType:@"pem"]; setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, [path cStringUsingEncoding:NSUTF8StringEncoding], 1); }); diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h index 4d4431ee365..fcbdfb21539 100644 --- a/src/objective-c/GRPCClient/private/version.h +++ b/src/objective-c/GRPCClient/private/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.20.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.21.0-dev" diff --git a/src/objective-c/README-CFSTREAM.md b/src/objective-c/README-CFSTREAM.md index 0cb25ab237b..184d5679cbb 100644 --- a/src/objective-c/README-CFSTREAM.md +++ b/src/objective-c/README-CFSTREAM.md @@ -6,24 +6,19 @@ sockets) for networking. Using CFStream resolves a bunch of network connectivity (see the [doc](https://github.com/grpc/grpc/blob/master/src/objective-c/NetworkTransitionBehavior.md) for more information). -CFStream integration is now in experimental state. You will need explicit opt-in to use it to get +CFStream integration is now in experimental state. You will need explicit opt-in to use it to get the benefits of resolving the issues above. We expect to make CFStream the default networking -interface that gRPC uses when it is ready for production. +interface that gRPC uses when it is ready for production. -## Usage -If you use gRPC following the instructions in -[README.md](https://github.com/grpc/grpc/blob/master/src/objective-c/README.md): -- Replace the -dependency on `gRPC-ProtoRPC` with `gRPC-ProtoRPC/CFStream`. -- Enable CFStream with environment variable `grpc_cfstream=1`. This can be done either in Xcode - console or by your code with `setenv()` before gRPC is initialized. - -If your project directly depends on podspecs other than `gRPC-ProtoRPC` (e.g. `gRPC` or -`gRPC-Core`): +As of v1.21.0, CFStream integration is now the default networking stack being used by gRPC +Objective-C on iOS layer. You get to use it automatically without special configuration needed. See +below on how to disable CFStream in case of problem. -- Make your projects depend on subspecs corresponding to CFStream in each gRPC podspec. -- Enable CFStream with environment variable `grpc_cfstream=1`. This can be done either in Xcode - console or by your code with `setenv()` before gRPC is initialized. +## Usage +If you use gRPC Objective-C library on iOS, CFStream is on automatically. If you use it on other +platforms, you can turn it on with macro `GRPC_CFSTREAM=1` for the pod 'gRPC-Core' and 'gRPC'. In +case of problem and you want to disable CFStream on iOS, you can set environment variable +"grpc\_cfstream=0". ## Notes diff --git a/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme new file mode 100644 index 00000000000..b9fb9d4d129 --- /dev/null +++ b/src/objective-c/manual_tests/GrpcIosTest.xcodeproj/xcshareddata/xcschemes/GrpcIosTest.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m b/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m index b0a929e689d..b5e19657ce7 100644 --- a/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m +++ b/src/objective-c/manual_tests/GrpcIosTestUITests/GrpcIosTestUITests.m @@ -19,6 +19,7 @@ #import NSTimeInterval const kWaitTime = 30; +int const kNumIterations = 1; @interface GrpcIosTestUITests : XCTestCase @end @@ -32,16 +33,27 @@ NSTimeInterval const kWaitTime = 30; self.continueAfterFailure = NO; [[[XCUIApplication alloc] init] launch]; testApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"io.grpc.GrpcIosTest"]; + [testApp activate]; + // Reset RPC counter + [self pressButton:@"Reset counter"]; + settingsApp = [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.Preferences"]; [settingsApp activate]; + [NSThread sleepForTimeInterval:1]; // Go back to the first page of Settings. XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch; - while (backButton.exists) { + while (backButton.exists && backButton.isHittable) { + NSLog(@"Tapping back button"); [backButton tap]; } XCTAssert([settingsApp.navigationBars[@"Settings"] waitForExistenceWithTimeout:kWaitTime]); + NSLog(@"Turning off airplane mode"); // Turn off airplane mode [self setAirplaneMode:NO]; + + // Turn on wifi + NSLog(@"Turning on wifi"); + [self setWifi:YES]; } - (void)tearDown { @@ -49,14 +61,25 @@ NSTimeInterval const kWaitTime = 30; - (void)doUnaryCall { [testApp activate]; - [testApp.buttons[@"Unary call"] tap]; + [self pressButton:@"Unary call"]; } -- (void)doStreamingCall { +- (void)do10UnaryCalls { [testApp activate]; - [testApp.buttons[@"Start streaming call"] tap]; - [testApp.buttons[@"Send Message"] tap]; - [testApp.buttons[@"Stop streaming call"] tap]; + [self pressButton:@"10 Unary calls"]; +} + +- (void)pressButton:(NSString *)name { + // Wait for button to be visible + while (![testApp.buttons[name] exists] || ![testApp.buttons[name] isHittable]) { + [NSThread sleepForTimeInterval:1]; + } + // Wait until all events in run loop have been processed + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true) == kCFRunLoopRunHandledSource) + ; + + NSLog(@"Pressing button: %@", name); + [testApp.buttons[name] tap]; } - (void)expectCallSuccess { @@ -71,41 +94,81 @@ NSTimeInterval const kWaitTime = 30; [settingsApp activate]; XCUIElement *mySwitch = settingsApp.tables.element.cells.switches[@"Airplane Mode"]; BOOL from = [(NSString *)mySwitch.value boolValue]; + NSLog(@"Setting airplane from: %d to: %d", from, to); if (from != to) { [mySwitch tap]; - // wait for gRPC to detect the change - sleep(10); + // wait for network change to finish + [NSThread sleepForTimeInterval:5]; } XCTAssert([(NSString *)mySwitch.value boolValue] == to); } +- (void)setWifi:(BOOL)to { + [settingsApp activate]; + [settingsApp.tables.element.cells.staticTexts[@"Wi-Fi"] tap]; + XCUIElement *wifiSwitch = settingsApp.tables.cells.switches[@"Wi-Fi"]; + BOOL from = [(NSString *)wifiSwitch.value boolValue]; + NSLog(@"Setting wifi from: %d to: %d", from, to); + if (from != to) { + [wifiSwitch tap]; + // wait for wifi networks to be detected + [NSThread sleepForTimeInterval:10]; + } + // Go back to the first page of Settings. + XCUIElement *backButton = settingsApp.navigationBars.buttons.firstMatch; + [backButton tap]; +} + +- (void)typeText:(NSString *)text inApp:(XCUIApplication *)app { + [app typeText:text]; + // Wait until all events in run loop have been processed + while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, true) == kCFRunLoopRunHandledSource) + ; +} -- (void)testBackgroundBeforeUnaryCall { +- (int)getRandomNumberBetween:(int)min max:(int)max { + return min + arc4random_uniform((max - min + 1)); +} + +- (void)testBackgroundBeforeCall { + NSLog(@"%s", __func__); // Open test app [testApp activate]; - // Send test app to background [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; - sleep(5); + + // Wait a bit + int sleepTime = [self getRandomNumberBetween:5 max:10]; + NSLog(@"Sleeping for %d seconds", sleepTime); + [NSThread sleepForTimeInterval:sleepTime]; // Bring test app to foreground and make a unary call. Call should succeed [self doUnaryCall]; [self expectCallSuccess]; } -- (void)testBackgroundBeforeStreamingCall { - // Open test app +- (void)testBackgroundDuringStreamingCall { + NSLog(@"%s", __func__); + // Open test app and start a streaming call [testApp activate]; + [self pressButton:@"Start streaming call"]; // Send test app to background [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; - sleep(5); + + // Wait a bit + int sleepTime = [self getRandomNumberBetween:5 max:10]; + NSLog(@"Sleeping for %d seconds", sleepTime); + [NSThread sleepForTimeInterval:sleepTime]; // Bring test app to foreground and make a streaming call. Call should succeed. - [self doStreamingCall]; + [testApp activate]; + [self pressButton:@"Send Message"]; + [self pressButton:@"Stop streaming call"]; [self expectCallSuccess]; } -- (void)testUnaryCallAfterNetworkFlap { +- (void)testCallAfterNetworkFlap { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; @@ -119,56 +182,150 @@ NSTimeInterval const kWaitTime = 30; [self expectCallSuccess]; } -- (void)testStreamingCallAfterNetworkFlap { +- (void)testCallWhileNetworkDown { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; - // Toggle airplane mode on and off + // Turn on airplane mode [self setAirplaneMode:YES]; + // Turn off wifi + [self setWifi:NO]; + + // Unary call should fail + [self doUnaryCall]; + [self expectCallFailed]; + + // Turn off airplane mode [self setAirplaneMode:NO]; + // Turn on wifi + [self setWifi:YES]; - [self doStreamingCall]; + // Unary call should succeed + [self doUnaryCall]; [self expectCallSuccess]; } -- (void)testUnaryCallWhileNetworkDown { +- (void)testSwitchApp { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; - // Turn on airplane mode - [self setAirplaneMode:YES]; + // Send test app to background + [XCUIDevice.sharedDevice pressButton:XCUIDeviceButtonHome]; - // Unary call should fail + // Open safari and goto a URL + XCUIApplication *safari = + [[XCUIApplication alloc] initWithBundleIdentifier:@"com.apple.mobilesafari"]; + [safari activate]; + // Ensure that safari is running in the foreground + XCTAssert([safari waitForState:XCUIApplicationStateRunningForeground timeout:5]); + // Move cursor to address bar + [safari.buttons[@"URL"] tap]; + // Wait for keyboard to appear + [NSThread sleepForTimeInterval:2]; + // Enter URL + [self typeText:@"http://maps.google.com" inApp:safari]; + // Presses return key + [self typeText:@"\n" inApp:safari]; + // Wait a bit + int sleepTime = [self getRandomNumberBetween:5 max:10]; + NSLog(@"Sleeping for %d seconds", sleepTime); + [NSThread sleepForTimeInterval:sleepTime]; + + // Make another unary call [self doUnaryCall]; + [self expectCallSuccess]; +} + +- (void)testNetworkFlapDuringStreamingCall { + NSLog(@"%s", __func__); + // Open test app and make a unary call. Channel to server should be open after this. + [self doUnaryCall]; + [self expectCallSuccess]; + // Start streaming call and send a message + [self pressButton:@"Start streaming call"]; + [self pressButton:@"Send Message"]; + + // Toggle network on and off + [self setAirplaneMode:YES]; + [self setWifi:NO]; + [self setAirplaneMode:NO]; + [self setWifi:YES]; + + [testApp activate]; + // We expect the call to have failed because the network flapped [self expectCallFailed]; +} - // Turn off airplane mode +- (void)testConcurrentCalls { + NSLog(@"%s", __func__); + + // Press button to start 10 unary calls + [self do10UnaryCalls]; + + // Toggle airplane mode on and off + [self setAirplaneMode:YES]; [self setAirplaneMode:NO]; - // Unary call should succeed + // 10 calls should have completed + [testApp activate]; + XCTAssert([testApp.staticTexts[@"Calls completed: 10"] waitForExistenceWithTimeout:kWaitTime]); +} + +- (void)invokeTest { + for (int i = 0; i < kNumIterations; i++) { + [super invokeTest]; + } +} + +- (void)testUnaryCallTurnOffWifi { + NSLog(@"%s", __func__); + // Open test app and make a unary call. Channel to server should be open after this. + [self doUnaryCall]; + [self expectCallSuccess]; + + // Turn off wifi + [self setWifi:NO]; + + // Phone should switch to cellular connection, call should succeed + [self doUnaryCall]; + [self expectCallSuccess]; + + // Turn on wifi + [self setWifi:YES]; + + // Call should succeed after turning wifi back on [self doUnaryCall]; [self expectCallSuccess]; } -- (void)testStreamingCallWhileNetworkDown { +- (void)testStreamingCallTurnOffWifi { + NSLog(@"%s", __func__); // Open test app and make a unary call. Channel to server should be open after this. [self doUnaryCall]; [self expectCallSuccess]; - // Turn on airplane mode - [self setAirplaneMode:YES]; + // Start streaming call and send a message + [self pressButton:@"Start streaming call"]; + [self pressButton:@"Send Message"]; + + // Turn off wifi + [self setWifi:NO]; - // Streaming call should fail - [self doStreamingCall]; + // Phone should switch to cellular connection, this results in the call failing + [testApp activate]; + [self pressButton:@"Stop streaming call"]; [self expectCallFailed]; - // Turn off airplane mode - [self setAirplaneMode:NO]; + // Turn on wifi + [self setWifi:YES]; - // Unary call should succeed - [self doStreamingCall]; + // Call should succeed after turning wifi back on + [self doUnaryCall]; [self expectCallSuccess]; } + @end diff --git a/src/objective-c/manual_tests/Main.storyboard b/src/objective-c/manual_tests/Main.storyboard index e7e0530efcd..409084126d0 100644 --- a/src/objective-c/manual_tests/Main.storyboard +++ b/src/objective-c/manual_tests/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -26,16 +26,8 @@ - + + + + + @@ -57,6 +87,7 @@ + diff --git a/src/objective-c/manual_tests/ViewController.m b/src/objective-c/manual_tests/ViewController.m index 813b176f3e8..50a729e4d6a 100644 --- a/src/objective-c/manual_tests/ViewController.m +++ b/src/objective-c/manual_tests/ViewController.m @@ -27,33 +27,36 @@ NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com"; const int32_t kMessageSize = 100; @interface ViewController : UIViewController -@property(strong, nonatomic) UILabel *fromLabel; +@property(strong, nonatomic) UILabel *callStatusLabel; +@property(strong, nonatomic) UILabel *callCountLabel; @end @implementation ViewController { RMTTestService *_service; dispatch_queue_t _dispatchQueue; GRPCStreamingProtoCall *_call; + int _calls_completed; } - (instancetype)init { self = [super init]; + _calls_completed = 0; return self; } - (void)viewDidLoad { [super viewDidLoad]; _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL); - _fromLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 500, 200, 20)]; - _fromLabel.textColor = [UIColor blueColor]; - _fromLabel.backgroundColor = [UIColor whiteColor]; - [self.view addSubview:_fromLabel]; + _callStatusLabel = (UILabel *)[self.view viewWithTag:1]; + _callCountLabel = (UILabel *)[self.view viewWithTag:2]; } -- (IBAction)tapUnaryCall:(id)sender { +- (void)startUnaryCall { if (_service == nil) { _service = [RMTTestService serviceWithHost:kRemoteHost]; } - self->_fromLabel.text = @""; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callStatusLabel.text = @""; + }); // Set up request proto message RMTSimpleRequest *request = [RMTSimpleRequest message]; @@ -63,14 +66,43 @@ const int32_t kMessageSize = 100; GRPCUnaryProtoCall *call = [_service unaryCallWithMessage:request responseHandler:self callOptions:nil]; + [call start]; } +- (IBAction)tapUnaryCall:(id)sender { + NSLog(@"In tapUnaryCall"); + [self startUnaryCall]; +} + +- (IBAction)tap10UnaryCalls:(id)sender { + NSLog(@"In tap10UnaryCalls"); + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { + // Background thread + for (int i = 0; i < 10; ++i) { + [self startUnaryCall]; + [NSThread sleepForTimeInterval:0.5]; + } + }); +} + +- (IBAction)resetCounter:(id)sender { + _calls_completed = 0; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callCountLabel.text = + [NSString stringWithFormat:@"Calls completed: %d", self->_calls_completed]; + self->_callStatusLabel.text = @""; + }); +} + - (IBAction)tapStreamingCallStart:(id)sender { + NSLog(@"In tapStreamingCallStart"); if (_service == nil) { _service = [RMTTestService serviceWithHost:kRemoteHost]; } - self->_fromLabel.text = @""; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callStatusLabel.text = @""; + }); // Set up request proto message RMTStreamingOutputCallRequest *request = RMTStreamingOutputCallRequest.message; @@ -83,10 +115,10 @@ const int32_t kMessageSize = 100; [call start]; _call = call; // display something to confirm the tester the call is started - NSLog(@"Started streaming call"); } - (IBAction)tapStreamingCallSend:(id)sender { + NSLog(@"In tapStreamingCallSend"); if (_call == nil) return; RMTStreamingOutputCallRequest *request = RMTStreamingOutputCallRequest.message; @@ -99,6 +131,7 @@ const int32_t kMessageSize = 100; } - (IBAction)tapStreamingCallStop:(id)sender { + NSLog(@"In tapStreamingCallStop"); if (_call == nil) return; [_call finish]; @@ -118,13 +151,18 @@ const int32_t kMessageSize = 100; NSLog(@"Recv trailing metadata: %@, error: %@", trailingMetadata, error); if (error == nil) { dispatch_async(dispatch_get_main_queue(), ^{ - self->_fromLabel.text = @"Call done"; + self->_callStatusLabel.text = @"Call done"; }); } else { dispatch_async(dispatch_get_main_queue(), ^{ - self->_fromLabel.text = @"Call failed"; + self->_callStatusLabel.text = @"Call failed"; }); } + ++_calls_completed; + dispatch_async(dispatch_get_main_queue(), ^{ + self->_callCountLabel.text = + [NSString stringWithFormat:@"Calls completed: %d", self->_calls_completed]; + }); } - (dispatch_queue_t)dispatchQueue { diff --git a/src/objective-c/tests/APIv2Tests/APIv2Tests.m b/src/objective-c/tests/APIv2Tests/APIv2Tests.m index ca7bf472830..ea777e27812 100644 --- a/src/objective-c/tests/APIv2Tests/APIv2Tests.m +++ b/src/objective-c/tests/APIv2Tests/APIv2Tests.m @@ -22,6 +22,7 @@ #import #include +#include #import "../version.h" @@ -198,7 +199,9 @@ static const NSTimeInterval kTestTimeout = 16; expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; expectedUserAgent = [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" ("]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@GPR_PLATFORM_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@"; chttp2; "]; expectedUserAgent = [expectedUserAgent stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]]; expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m index 3ef046835e4..b361078d54b 100644 --- a/src/objective-c/tests/GRPCClientTests.m +++ b/src/objective-c/tests/GRPCClientTests.m @@ -16,9 +16,9 @@ * */ -#import #import #import +#import #import #import @@ -297,7 +297,9 @@ static GRPCProtoMethod *kFullDuplexCallMethod; expectedUserAgent = [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING]; expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"]; expectedUserAgent = [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING]; - expectedUserAgent = [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@" ("]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@GPR_PLATFORM_STRING]; + expectedUserAgent = [expectedUserAgent stringByAppendingString:@"; chttp2; "]; expectedUserAgent = [expectedUserAgent stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]]; expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"]; diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m index 717dfd81f7d..b6bc3f4bc7f 100644 --- a/src/objective-c/tests/InteropTests.m +++ b/src/objective-c/tests/InteropTests.m @@ -20,7 +20,9 @@ #include +#ifdef GRPC_COMPILE_WITH_CRONET #import +#endif #import #import #import @@ -753,7 +755,7 @@ BOOL isRemoteInteropTest(NSString *host) { [GRPCCall closeOpenConnections]; #pragma clang diagnostic pop - [_service + [self->_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) { XCTAssertNil( diff --git a/src/objective-c/tests/MacTests/Info.plist b/src/objective-c/tests/MacTests/Info.plist new file mode 100644 index 00000000000..6c40a6cd0c4 --- /dev/null +++ b/src/objective-c/tests/MacTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile index 8e5f588906b..4906e5b45a4 100644 --- a/src/objective-c/tests/Podfile +++ b/src/objective-c/tests/Podfile @@ -1,5 +1,4 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' install! 'cocoapods', :deterministic_uuids => false @@ -17,9 +16,13 @@ GRPC_LOCAL_SRC = '../../..' InteropTestsMultipleChannels InteropTestsCallOptions UnitTests + InteropTestsRemoteCFStream + InteropTestsLocalSSLCFStream + InteropTestsLocalCleartextCFStream APIv2Tests ).each do |target_name| target target_name do + platform :ios, '8.0' pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" @@ -40,25 +43,20 @@ GRPC_LOCAL_SRC = '../../..' end end -%w( - InteropTestsRemoteCFStream - InteropTestsLocalSSLCFStream - InteropTestsLocalCleartextCFStream -).each do |target_name| - target target_name do - pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true +target 'MacTests' do + platform :osx, '10.13' + pod 'Protobuf', :path => "#{GRPC_LOCAL_SRC}/third_party/protobuf", :inhibit_warnings => true - pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" - pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + pod '!ProtoCompiler', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" + pod '!ProtoCompiler-gRPCPlugin', :path => "#{GRPC_LOCAL_SRC}/src/objective-c" - pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true + pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true - pod 'gRPC/CFStream', :path => GRPC_LOCAL_SRC - pod 'gRPC-Core/CFStream-Implementation', :path => GRPC_LOCAL_SRC - pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC - pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true - pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true - end + pod 'gRPC', :path => GRPC_LOCAL_SRC + pod 'gRPC-Core', :path => GRPC_LOCAL_SRC + pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC + pod 'gRPC-ProtoRPC', :path => GRPC_LOCAL_SRC, :inhibit_warnings => true + pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true end %w( @@ -66,6 +64,7 @@ end CronetUnitTests ).each do |target_name| target target_name do + platform :ios, '8.0' pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c" pod 'gRPC-Core', :path => GRPC_LOCAL_SRC @@ -76,6 +75,7 @@ end end target 'ChannelTests' do + platform :ios, '8.0' pod 'gRPC', :path => GRPC_LOCAL_SRC pod 'gRPC-Core', :path => GRPC_LOCAL_SRC pod 'BoringSSL-GRPC', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true @@ -127,11 +127,7 @@ post_install do |installer| # GPR_UNREACHABLE_CODE causes "Control may reach end of non-void # function" warning config.build_settings['GCC_WARN_ABOUT_RETURN_TYPE'] = 'NO' - if target.name.include?('CFStream') - config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CFSTREAM=1' - else - config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' - end + config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_CRONET_WITH_PACKET_COALESCING=1' end end @@ -139,7 +135,7 @@ post_install do |installer| # the test target 'InteropTestsRemoteWithCronet' # Activate GRPCCall+InternalTests functions for the dedicated build configuration 'Test', which will # be used by all test targets using it. - if target.name == 'gRPC' || target.name.start_with?('gRPC.') + if /gRPC-(mac|i)OS/.match(target.name) target.build_configurations.each do |config| if config.name == 'Cronet' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) COCOAPODS=1 GRPC_COMPILE_WITH_CRONET=1 GRPC_TEST_OBJC=1' @@ -150,9 +146,7 @@ post_install do |installer| end # Enable NSAssert on gRPC - if target.name == 'gRPC' || target.name.start_with?('gRPC.') || - target.name == 'ProtoRPC' || target.name.start_with?('ProtoRPC.') || - target.name == 'RxLibrary' || target.name.start_with?('RxLibrary.') + if /(gRPC|ProtoRPC|RxLibrary)-(mac|i)OS/.match(target.name) target.build_configurations.each do |config| if config.name != 'Release' config.build_settings['ENABLE_NS_ASSERTIONS'] = 'YES' diff --git a/src/objective-c/tests/RxLibraryUnitTests.m b/src/objective-c/tests/RxLibraryUnitTests.m index ecd914c9b5f..2faf57ef938 100644 --- a/src/objective-c/tests/RxLibraryUnitTests.m +++ b/src/objective-c/tests/RxLibraryUnitTests.m @@ -16,7 +16,6 @@ * */ -#import #import #import @@ -44,9 +43,9 @@ - (GRXSingleHandler)block { return ^(id value, NSError *errorOrNil) { - ++_timesCalled; - _value = value; - _errorOrNil = errorOrNil; + ++self->_timesCalled; + self->_value = value; + self->_errorOrNil = errorOrNil; }; } @end diff --git a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj index b6762cc6001..d4f93b516fa 100644 --- a/src/objective-c/tests/Tests.xcodeproj/project.pbxproj +++ b/src/objective-c/tests/Tests.xcodeproj/project.pbxproj @@ -66,7 +66,17 @@ 6C1A3F81CCF7C998B4813EFD /* libPods-InteropTestsCallOptions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */; }; 886717A79EFF774F356798E6 /* libPods-InteropTestsMultipleChannels.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 355D0E30AD224763BC9519F4 /* libPods-InteropTestsMultipleChannels.a */; }; 91D4B3C85B6D8562F409CB48 /* libPods-InteropTestsLocalSSLCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F3AB031E0E26AC8EF30A2A2A /* libPods-InteropTestsLocalSSLCFStream.a */; }; + 953CD2942A3A6D6CE695BE87 /* libPods-MacTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 276873A05AC5479B60DF6079 /* libPods-MacTests.a */; }; 98478C9F42329DF769A45B6C /* libPods-APIv2Tests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */; }; + B0BB3F02225E7A3C008DA580 /* InteropTestsLocalSSL.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E240CD1B6C4E2B005F3B0E /* InteropTestsLocalSSL.m */; }; + B0BB3F03225E7A44008DA580 /* InteropTestsLocalCleartext.m in Sources */ = {isa = PBXBuildFile; fileRef = 63715F551B780C020029CB0B /* InteropTestsLocalCleartext.m */; }; + B0BB3F04225E7A8D008DA580 /* RxLibraryUnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63423F501B151B77006CF63C /* RxLibraryUnitTests.m */; }; + B0BB3F05225E7A9F008DA580 /* InteropTestsRemote.m in Sources */ = {isa = PBXBuildFile; fileRef = 6379CC4F1BE16703001BC0A1 /* InteropTestsRemote.m */; }; + B0BB3F06225E7AAD008DA580 /* GRPCClientTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6312AE4D1B1BF49B00341DEE /* GRPCClientTests.m */; }; + B0BB3F07225E7AB5008DA580 /* APIv2Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E3B95A421CAC6C500C0A151 /* APIv2Tests.m */; }; + B0BB3F08225E7ABA008DA580 /* UnitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E0282E8215AA697007AC99D /* UnitTests.m */; }; + B0BB3F0A225EA511008DA580 /* TestCertificates.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 63E240CF1B6C63DC005F3B0E /* TestCertificates.bundle */; }; + B0BB3F0B225EB110008DA580 /* InteropTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 635ED2EB1B1A3BC400FDE5C3 /* InteropTests.m */; }; BC111C80CBF7068B62869352 /* libPods-InteropTestsRemoteCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F44AC3F44E3491A8C0D890FE /* libPods-InteropTestsRemoteCFStream.a */; }; C3D6F4270A2FFF634D8849ED /* libPods-InteropTestsLocalCleartextCFStream.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BDA4BA011779D5D25B5618C /* libPods-InteropTestsLocalCleartextCFStream.a */; }; CCF5C0719EF608276AE16374 /* libPods-UnitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */; }; @@ -183,10 +193,14 @@ 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-APIv2Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests.release.xcconfig"; sourceTree = ""; }; 14B09A58FEE53A7A6B838920 /* Pods-InteropTestsLocalSSL.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalSSL.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL.cronet.xcconfig"; sourceTree = ""; }; 1588C85DEAF7FC0ACDEA4C02 /* Pods-InteropTestsLocalCleartext.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.test.xcconfig"; sourceTree = ""; }; + 16A2E4C5839C83FBDA63881F /* Pods-MacTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MacTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-MacTests/Pods-MacTests.cronet.xcconfig"; sourceTree = ""; }; 17F60BF2871F6AF85FB3FA12 /* Pods-InteropTestsRemoteWithCronet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.debug.xcconfig"; sourceTree = ""; }; + 1E43EAE443CBB4482B1EB071 /* Pods-MacTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MacTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-MacTests/Pods-MacTests.release.xcconfig"; sourceTree = ""; }; + 1F5E788FBF9A4A06EB9E1ACD /* Pods-MacTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MacTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-MacTests/Pods-MacTests.test.xcconfig"; sourceTree = ""; }; 20DFF2F3C97EF098FE5A3171 /* libPods-Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-UnitTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 2650FEF00956E7924772F9D9 /* Pods-InteropTestsMultipleChannels.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsMultipleChannels.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels.release.xcconfig"; sourceTree = ""; }; + 276873A05AC5479B60DF6079 /* libPods-MacTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MacTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 2B89F3037963E6EDDD48D8C3 /* Pods-InteropTestsRemoteWithCronet.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.test.xcconfig"; sourceTree = ""; }; 303F4A17EB1650FC44603D17 /* Pods-InteropTestsRemoteCFStream.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.release.xcconfig"; sourceTree = ""; }; 32748C4078AEB05F8F954361 /* Pods-InteropTestsRemoteCFStream.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteCFStream.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream.debug.xcconfig"; sourceTree = ""; }; @@ -274,6 +288,8 @@ AA7CB64B4DD9915AE7C03163 /* Pods-InteropTestsLocalCleartext.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.cronet.xcconfig"; sourceTree = ""; }; AC414EF7A6BF76ED02B6E480 /* Pods-InteropTestsRemoteWithCronet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemoteWithCronet.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet.release.xcconfig"; sourceTree = ""; }; AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-InteropTestsCallOptions.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + B0BB3EF7225E795F008DA580 /* MacTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MacTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + B0BB3EFB225E795F008DA580 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B226619DC4E709E0FFFF94B8 /* Pods-CronetUnitTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CronetUnitTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-CronetUnitTests/Pods-CronetUnitTests.test.xcconfig"; sourceTree = ""; }; B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-APIv2Tests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B94C27C06733CF98CE1B2757 /* Pods-AllTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.debug.xcconfig"; sourceTree = ""; }; @@ -290,6 +306,7 @@ DC3CA1D948F068E76957A861 /* Pods-InteropTestsRemote.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.debug.xcconfig"; sourceTree = ""; }; E1486220285AF123EB124008 /* Pods-InteropTestsLocalCleartext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartext.debug.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext.debug.xcconfig"; sourceTree = ""; }; E1E7660656D902104F728892 /* Pods-UnitTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnitTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests.cronet.xcconfig"; sourceTree = ""; }; + E3ACD4D5902745976D9C2229 /* Pods-MacTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MacTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MacTests/Pods-MacTests.debug.xcconfig"; sourceTree = ""; }; E4275A759BDBDF143B9B438F /* Pods-InteropTestsRemote.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsRemote.release.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote.release.xcconfig"; sourceTree = ""; }; E4FD4606D4AB8D5A314D72F0 /* Pods-InteropTestsLocalCleartextCFStream.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; path = "Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream.test.xcconfig"; sourceTree = ""; }; E7E4D3FD76E3B745D992AF5F /* Pods-AllTests.cronet.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AllTests.cronet.xcconfig"; path = "Pods/Target Support Files/Pods-AllTests/Pods-AllTests.cronet.xcconfig"; sourceTree = ""; }; @@ -451,6 +468,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B0BB3EF4225E795F008DA580 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 953CD2942A3A6D6CE695BE87 /* libPods-MacTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -475,6 +500,7 @@ AF3FC2CFFE7B0961823BC740 /* libPods-InteropTestsCallOptions.a */, 22A3EBB488699C8CEA19707B /* libPods-UnitTests.a */, B6AD69CACF67505B0F028E92 /* libPods-APIv2Tests.a */, + 276873A05AC5479B60DF6079 /* libPods-MacTests.a */, ); name = Frameworks; sourceTree = ""; @@ -548,6 +574,10 @@ 51F2A64B7AADBA1B225B132E /* Pods-APIv2Tests.test.xcconfig */, 8C233E85C3EB45B3CAE52EDF /* Pods-APIv2Tests.cronet.xcconfig */, 12B238CD1702393C2BA5DE80 /* Pods-APIv2Tests.release.xcconfig */, + E3ACD4D5902745976D9C2229 /* Pods-MacTests.debug.xcconfig */, + 1F5E788FBF9A4A06EB9E1ACD /* Pods-MacTests.test.xcconfig */, + 16A2E4C5839C83FBDA63881F /* Pods-MacTests.cronet.xcconfig */, + 1E43EAE443CBB4482B1EB071 /* Pods-MacTests.release.xcconfig */, ); name = Pods; sourceTree = ""; @@ -637,6 +667,7 @@ 5E7D71B3210B9EC9001EA6BA /* InteropTestsCallOptions */, 5E0282E7215AA697007AC99D /* UnitTests */, 5E3B95A321CAC6C500C0A151 /* APIv2Tests */, + B0BB3EF8225E795F008DA580 /* MacTests */, 635697C81B14FC11007A7283 /* Products */, 51E4650F34F854F41FF053B3 /* Pods */, 136D535E19727099B941D7B1 /* Frameworks */, @@ -663,6 +694,7 @@ 5E7D71B2210B9EC8001EA6BA /* InteropTestsCallOptions.xctest */, 5E0282E6215AA697007AC99D /* UnitTests.xctest */, 5E3B95A221CAC6C500C0A151 /* APIv2Tests.xctest */, + B0BB3EF7225E795F008DA580 /* MacTests.xctest */, ); name = Products; sourceTree = ""; @@ -692,6 +724,14 @@ name = "Supporting Files"; sourceTree = ""; }; + B0BB3EF8225E795F008DA580 /* MacTests */ = { + isa = PBXGroup; + children = ( + B0BB3EFB225E795F008DA580 /* Info.plist */, + ); + path = MacTests; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1030,6 +1070,25 @@ productReference = 63DC84431BE152B5000708E8 /* InteropTestsLocalCleartext.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + B0BB3EF6225E795F008DA580 /* MacTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = B0BB3EFC225E795F008DA580 /* Build configuration list for PBXNativeTarget "MacTests" */; + buildPhases = ( + E5B20F69559C6AE299DFEA7C /* [CP] Check Pods Manifest.lock */, + B0BB3EF3225E795F008DA580 /* Sources */, + B0BB3EF4225E795F008DA580 /* Frameworks */, + B0BB3EF5225E795F008DA580 /* Resources */, + 452FDC3918FEC23ECAFD31EC /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MacTests; + productName = MacTests; + productReference = B0BB3EF7225E795F008DA580 /* MacTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -1098,6 +1157,10 @@ 63DC84421BE152B5000708E8 = { CreatedOnToolsVersion = 7.0.1; }; + B0BB3EF6225E795F008DA580 = { + CreatedOnToolsVersion = 10.1; + ProvisioningStyle = Automatic; + }; }; }; buildConfigurationList = 635697C21B14FC11007A7283 /* Build configuration list for PBXProject "Tests" */; @@ -1129,6 +1192,7 @@ 5E7D71B1210B9EC8001EA6BA /* InteropTestsCallOptions */, 5E0282E5215AA697007AC99D /* UnitTests */, 5E3B95A121CAC6C500C0A151 /* APIv2Tests */, + B0BB3EF6225E795F008DA580 /* MacTests */, ); }; /* End PBXProject section */ @@ -1250,6 +1314,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B0BB3EF5225E795F008DA580 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B0BB3F0A225EA511008DA580 /* TestCertificates.bundle in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -1278,7 +1350,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsMultipleChannels/Pods-InteropTestsMultipleChannels-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1296,7 +1368,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-ChannelTests/Pods-ChannelTests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1361,6 +1433,28 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; + 452FDC3918FEC23ECAFD31EC /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-MacTests/Pods-MacTests-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-macOS/gRPCCertificates.bundle", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/gRPCCertificates.bundle", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-MacTests/Pods-MacTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 483CDBBAEAEFCB530ADDDDD5 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -1404,7 +1498,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSLCFStream/Pods-InteropTestsLocalSSLCFStream-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC.default-CFStream/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1440,7 +1534,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalSSL/Pods-InteropTestsLocalSSL-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1458,7 +1552,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsCallOptions/Pods-InteropTestsCallOptions-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1512,7 +1606,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalCleartext/Pods-InteropTestsLocalCleartext-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1584,7 +1678,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteCFStream/Pods-InteropTestsRemoteCFStream-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC.default-CFStream/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1602,7 +1696,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-UnitTests/Pods-UnitTests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1620,7 +1714,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsLocalCleartextCFStream/Pods-InteropTestsLocalCleartextCFStream-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC.default-CFStream/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1638,7 +1732,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-AllTests/Pods-AllTests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1712,7 +1806,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-APIv2Tests/Pods-APIv2Tests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( @@ -1732,7 +1826,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemote/Pods-InteropTestsRemote-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1750,7 +1844,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-RxLibraryUnitTests/Pods-RxLibraryUnitTests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1768,7 +1862,7 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/gRPC/gRPCCertificates.bundle", + "${PODS_CONFIGURATION_BUILD_DIR}/gRPC-iOS/gRPCCertificates.bundle", ); name = "[CP] Copy Pods Resources"; outputPaths = ( @@ -1779,6 +1873,28 @@ shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-InteropTestsRemoteWithCronet/Pods-InteropTestsRemoteWithCronet-resources.sh\"\n"; showEnvVarsInLog = 0; }; + E5B20F69559C6AE299DFEA7C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-MacTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; E63468C760D0724F18861822 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -2027,6 +2143,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + B0BB3EF3225E795F008DA580 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + B0BB3F07225E7AB5008DA580 /* APIv2Tests.m in Sources */, + B0BB3F08225E7ABA008DA580 /* UnitTests.m in Sources */, + B0BB3F05225E7A9F008DA580 /* InteropTestsRemote.m in Sources */, + B0BB3F03225E7A44008DA580 /* InteropTestsLocalCleartext.m in Sources */, + B0BB3F04225E7A8D008DA580 /* RxLibraryUnitTests.m in Sources */, + B0BB3F0B225EB110008DA580 /* InteropTests.m in Sources */, + B0BB3F02225E7A3C008DA580 /* InteropTestsLocalSSL.m in Sources */, + B0BB3F06225E7AAD008DA580 /* GRPCClientTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -3886,6 +4017,154 @@ }; name = Release; }; + B0BB3EFD225E795F008DA580 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E3ACD4D5902745976D9C2229 /* Pods-MacTests.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = MacTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.MacTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Debug; + }; + B0BB3EFE225E795F008DA580 /* Test */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1F5E788FBF9A4A06EB9E1ACD /* Pods-MacTests.test.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "COCOAPODS=1", + "GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS=1", + "PB_FIELD_32BIT=1", + "PB_NO_PACKED_STRUCTS=1", + "PB_ENABLE_MALLOC=1", + "GRPC_TEST_OBJC=1", + ); + INFOPLIST_FILE = MacTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.MacTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Test; + }; + B0BB3EFF225E795F008DA580 /* Cronet */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 16A2E4C5839C83FBDA63881F /* Pods-MacTests.cronet.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = MacTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.MacTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Cronet; + }; + B0BB3F00225E795F008DA580 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1E43EAE443CBB4482B1EB071 /* Pods-MacTests.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = MacTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.grpc.MacTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -4087,6 +4366,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + B0BB3EFC225E795F008DA580 /* Build configuration list for PBXNativeTarget "MacTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B0BB3EFD225E795F008DA580 /* Debug */, + B0BB3EFE225E795F008DA580 /* Test */, + B0BB3EFF225E795F008DA580 /* Cronet */, + B0BB3F00225E795F008DA580 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 635697BF1B14FC11007A7283 /* Project object */; diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme index b0bb9337640..a2560fee029 100644 --- a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme @@ -26,7 +26,6 @@ buildConfiguration = "Test" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme new file mode 100644 index 00000000000..77f567db3d4 --- /dev/null +++ b/src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/tests/UnitTests/UnitTests.m b/src/objective-c/tests/UnitTests/UnitTests.m index 57e686d1b67..4dcb8c08d28 100644 --- a/src/objective-c/tests/UnitTests/UnitTests.m +++ b/src/objective-c/tests/UnitTests/UnitTests.m @@ -20,7 +20,7 @@ #import -#import "src/objective-c/GRPCClient/private/NSError+GRPC.h" +#import "../../GRPCClient/private/NSError+GRPC.h" @interface UnitTests : XCTestCase diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh index f6fea96920e..8c768cb85be 100755 --- a/src/objective-c/tests/run_tests.sh +++ b/src/objective-c/tests/run_tests.sh @@ -195,4 +195,17 @@ xcodebuild \ | egrep -v '^$' \ | egrep -v "(GPBDictionary|GPBArray)" - +echo "TIME: $(date)" +xcodebuild \ + -workspace Tests.xcworkspace \ + -scheme MacTests \ + -destination platform=macOS \ + HOST_PORT_LOCALSSL=localhost:5051 \ + HOST_PORT_LOCAL=localhost:5050 \ + HOST_PORT_REMOTE=grpc-test.sandbox.googleapis.com \ + test \ + | egrep -v "$XCODEBUILD_FILTER" \ + | egrep -v '^$' \ + | egrep -v "(GPBDictionary|GPBArray)" - + exit 0 diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index b3c4788f496..87516de11e8 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.20.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.21.0-dev" #define GRPC_C_VERSION_STRING @"7.0.0" diff --git a/src/php/composer.json b/src/php/composer.json index e8106db7288..a9d0aebffca 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Developement use only", "license": "Apache-2.0", - "version": "1.20.0", + "version": "1.21.0", "require": { "php": ">=5.5.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c index fa6f0be837b..3064563d03f 100644 --- a/src/php/ext/grpc/php_grpc.c +++ b/src/php/ext/grpc/php_grpc.c @@ -67,27 +67,22 @@ ZEND_GET_MODULE(grpc) /* {{{ PHP_INI */ -/* Remove comments and fill if you need to have entries in php.ini PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("grpc.global_value", "42", PHP_INI_ALL, OnUpdateLong, - global_value, zend_grpc_globals, grpc_globals) - STD_PHP_INI_ENTRY("grpc.global_string", "foobar", PHP_INI_ALL, - OnUpdateString, global_string, zend_grpc_globals, - grpc_globals) + STD_PHP_INI_ENTRY("grpc.enable_fork_support", "0", PHP_INI_SYSTEM, OnUpdateBool, + enable_fork_support, zend_grpc_globals, grpc_globals) + STD_PHP_INI_ENTRY("grpc.poll_strategy", NULL, PHP_INI_SYSTEM, OnUpdateString, + poll_strategy, zend_grpc_globals, grpc_globals) PHP_INI_END() -*/ /* }}} */ /* {{{ php_grpc_init_globals */ -/* Uncomment this function if you have INI entries - static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) - { - grpc_globals->global_value = 0; - grpc_globals->global_string = NULL; - } -*/ +static void php_grpc_init_globals(zend_grpc_globals *grpc_globals) { + grpc_globals->enable_fork_support = 0; + grpc_globals->poll_strategy = NULL; +} /* }}} */ + void create_new_channel( wrapped_grpc_channel *channel, char *target, @@ -180,7 +175,7 @@ void postfork_child() { grpc_php_shutdown_completion_queue(TSRMLS_C); // clean-up grpc_core - grpc_shutdown(); + grpc_shutdown_blocking(); if (grpc_is_initialized() > 0) { zend_throw_exception(spl_ce_UnexpectedValueException, "Oops, failed to shutdown gRPC Core after fork()", @@ -208,12 +203,22 @@ void register_fork_handlers() { } } +void apply_ini_settings() { + if (GRPC_G(enable_fork_support)) { + setenv("GRPC_ENABLE_FORK_SUPPORT", "1", 1 /* overwrite? */); + } + + if (GRPC_G(poll_strategy)) { + setenv("GRPC_POLL_STRATEGY", GRPC_G(poll_strategy), 1 /* overwrite? */); + } +} + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(grpc) { - /* If you have INI entries, uncomment these lines - REGISTER_INI_ENTRIES(); - */ + ZEND_INIT_MODULE_GLOBALS(grpc, php_grpc_init_globals, NULL); + REGISTER_INI_ENTRIES(); + /* Register call error constants */ REGISTER_LONG_CONSTANT("Grpc\\CALL_OK", GRPC_CALL_OK, CONST_CS | CONST_PERSISTENT); @@ -349,9 +354,7 @@ PHP_MINIT_FUNCTION(grpc) { /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(grpc) { - /* uncomment this line if you have INI entries - UNREGISTER_INI_ENTRIES(); - */ + UNREGISTER_INI_ENTRIES(); // WARNING: This function IS being called by PHP when the extension // is unloaded but the logs were somehow suppressed. if (GRPC_G(initialized)) { @@ -375,9 +378,7 @@ PHP_MINFO_FUNCTION(grpc) { php_info_print_table_row(2, "grpc support", "enabled"); php_info_print_table_row(2, "grpc module version", PHP_GRPC_VERSION); php_info_print_table_end(); - /* Remove comments if you have entries in php.ini - DISPLAY_INI_ENTRIES(); - */ + DISPLAY_INI_ENTRIES(); } /* }}} */ @@ -385,6 +386,7 @@ PHP_MINFO_FUNCTION(grpc) { */ PHP_RINIT_FUNCTION(grpc) { if (!GRPC_G(initialized)) { + apply_ini_settings(); grpc_init(); register_fork_handlers(); grpc_php_init_completion_queue(TSRMLS_C); diff --git a/src/php/ext/grpc/php_grpc.h b/src/php/ext/grpc/php_grpc.h index ecf5ebaa05b..2629b1bbd78 100644 --- a/src/php/ext/grpc/php_grpc.h +++ b/src/php/ext/grpc/php_grpc.h @@ -66,6 +66,8 @@ PHP_RINIT_FUNCTION(grpc); */ ZEND_BEGIN_MODULE_GLOBALS(grpc) zend_bool initialized; + zend_bool enable_fork_support; + char *poll_strategy; ZEND_END_MODULE_GLOBALS(grpc) /* In every utility function you add that needs to use variables diff --git a/src/php/ext/grpc/tests/grpc-default-ini.phpt b/src/php/ext/grpc/tests/grpc-default-ini.phpt new file mode 100644 index 00000000000..0fbcc1f119e --- /dev/null +++ b/src/php/ext/grpc/tests/grpc-default-ini.phpt @@ -0,0 +1,15 @@ +--TEST-- +Ensure default ini settings +--SKIPIF-- + +--FILE-- + +--INI-- +grpc.enable_fork_support = 1 +grpc.poll_strategy = epoll1 +--FILE-- + 'GRPC_CFSTREAM=1' - } - ss.source_files = ${ruby_multiline_list(cfstream_private_files(filegroups), 22)} - ss.private_header_files = ${ruby_multiline_list(cfstream_private_headers(filegroups), 30)} end s.subspec 'Cronet-Interface' do |ss| diff --git a/templates/gRPC-ProtoRPC.podspec.template b/templates/gRPC-ProtoRPC.podspec.template index 9d7e392a24a..e4d5f3ffd3d 100644 --- a/templates/gRPC-ProtoRPC.podspec.template +++ b/templates/gRPC-ProtoRPC.podspec.template @@ -55,12 +55,10 @@ ss.source_files = "#{src_dir}/*.{h,m}" end + + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC/CFStream', version ss.dependency "#{s.name}/Main", version - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.pod_target_xcconfig = { diff --git a/templates/gRPC.podspec.template b/templates/gRPC.podspec.template index 6fe20e6c0c4..c9723933fcd 100644 --- a/templates/gRPC.podspec.template +++ b/templates/gRPC.podspec.template @@ -66,14 +66,9 @@ ss.dependency 'gRPC-Core', version end - # This subspec is mutually exclusive with the `Main` subspec + # CFStream is now default. Leaving this subspec only for compatibility purpose. s.subspec 'CFStream' do |ss| - ss.dependency 'gRPC-Core/CFStream-Implementation', version ss.dependency "#{s.name}/Main", version - - ss.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => 'GRPC_CFSTREAM=1' - } end s.subspec 'GID' do |ss| diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template index 0e321717c99..d2b54a9c2f5 100644 --- a/templates/grpc.gemspec.template +++ b/templates/grpc.gemspec.template @@ -32,7 +32,7 @@ s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.7' - s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' + s.add_dependency 'googleapis-common-protos-types', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' diff --git a/templates/src/csharp/Grpc.Core/Internal/native_methods.include b/templates/src/csharp/Grpc.Core/Internal/native_methods.include index b7a8e285488..e8ec4c87b06 100644 --- a/templates/src/csharp/Grpc.Core/Internal/native_methods.include +++ b/templates/src/csharp/Grpc.Core/Internal/native_methods.include @@ -44,7 +44,7 @@ native_method_signatures = [ 'void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value)', 'void grpcsharp_channel_args_destroy(IntPtr args)', 'void grpcsharp_override_default_ssl_roots(string pemRootCerts)', - 'ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey)', + 'ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag)', 'ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds)', 'void grpcsharp_channel_credentials_release(IntPtr credentials)', 'ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs)', diff --git a/templates/tools/dockerfile/bazel.include b/templates/tools/dockerfile/bazel.include index 62d68607453..8888e938f43 100644 --- a/templates/tools/dockerfile/bazel.include +++ b/templates/tools/dockerfile/bazel.include @@ -2,6 +2,6 @@ # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} - bash ./bazel-0.20.0-installer-linux-x86_64.sh && ${'\\'} - rm bazel-0.20.0-installer-linux-x86_64.sh +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-installer-linux-x86_64.sh && ${'\\'} + bash ./bazel-0.23.2-installer-linux-x86_64.sh && ${'\\'} + rm bazel-0.23.2-installer-linux-x86_64.sh diff --git a/templates/tools/dockerfile/cmake_jessie_backports.include b/templates/tools/dockerfile/cmake_jessie_backports.include index 2fc49dc8d60..7deaccde428 100644 --- a/templates/tools/dockerfile/cmake_jessie_backports.include +++ b/templates/tools/dockerfile/cmake_jessie_backports.include @@ -2,5 +2,7 @@ # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/templates/tools/dockerfile/debian_jessie_header.include b/templates/tools/dockerfile/debian_jessie_header.include new file mode 100644 index 00000000000..11bd5f9b129 --- /dev/null +++ b/templates/tools/dockerfile/debian_jessie_header.include @@ -0,0 +1,2 @@ +FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list diff --git a/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template b/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template index c5ec66ae290..55ebe7b1802 100644 --- a/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template +++ b/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../debian_jessie_header.include"/> <%include file="../clang5.include"/> ADD clang_format_all_the_things.sh / diff --git a/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template b/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template index bbdba700752..044da526feb 100644 --- a/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template +++ b/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../debian_jessie_header.include"/> <%include file="../clang5.include"/> <%include file="../python_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template index 53c5adae0d1..05ad947e944 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh.template @@ -25,12 +25,18 @@ cp -r /var/local/jenkins/service_account $HOME || true cd /var/local/git/grpc-dotnet - + # If needed, update dotnet SDK and put it on path ./build/get-dotnet.sh - if [ -f $HOME/.dotnet/dotnet ] + # Normally we would source ./activate.sh + # to add dotnet to PATH, but that would only + # work for the build and not for a subsequent + # dotnet run from a different shell, + # so we create a symlink instead. + # TODO(jtattermusch): Come up with a cleaner solution. + if [ -f $(pwd)/.dotnet/dotnet ] then - ln -s $HOME/.dotnet/dotnet /usr/local/bin/dotnet + ln -s $(pwd)/.dotnet/dotnet /usr/local/bin/dotnet fi ./build/get-grpc.sh diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile.template index 49493e624b3..dbb3ffc9bb2 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../python_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include index 24b9c59e4c7..7307e29f0a0 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include +++ b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include @@ -12,16 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM debian:jessie +<%include file="../../debian_jessie_header.include"/> <%include file="java_deps.include"/> -<%include file="../../python_deps.include"/> - -# Trigger download of as many Gradle artifacts as possible. -RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && ${'\\'} - cd grpc-java && ${'\\'} - ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true && ${'\\'} - rm -r "$(pwd)" # Define the default command. -CMD ["bash"] \ No newline at end of file +CMD ["bash"] diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include index 40d70e06d1a..c05b5642393 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include +++ b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/java_deps.include @@ -1,16 +1,11 @@ -# Install JDK 8 and Git +# Install JDK 8 # 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/ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && ${'\\'} + apt-get update && apt-get -y install 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 diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile.template index 6f098eb8266..ec6cd2970b1 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../python_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile.template index e53d863c92d..1b761c3ef05 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../node_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile.template index 06b0a4c0263..7a0ece69ac5 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../php_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile.template index 466bf6838ab..fe71c76251d 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../php7_deps.include"/> <%include file="../../run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile.template index 0610a288a68..ae9dd12070f 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../python_deps.include"/> diff --git a/templates/tools/dockerfile/java_build_interop.sh.include b/templates/tools/dockerfile/java_build_interop.sh.include index 16d5fb65cf1..e30b53e3f2a 100755 --- a/templates/tools/dockerfile/java_build_interop.sh.include +++ b/templates/tools/dockerfile/java_build_interop.sh.include @@ -16,16 +16,24 @@ # Builds Java interop server and client in a base image. set -e -mkdir -p /var/local/git -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java +cp -r /var/local/jenkins/grpc-java /tmp/grpc-java # copy service account keys if available cp -r /var/local/jenkins/service_account $HOME || true -cd /var/local/git/grpc-java - +pushd /tmp/grpc-java ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true +mkdir -p /var/local/git/grpc-java/ +cp -r --parents -t /var/local/git/grpc-java/ ${'\\'} + interop-testing/build/install/ ${'\\'} + run-test-client.sh ${'\\'} + run-test-server.sh + +popd +rm -r /tmp/grpc-java +rm -r "$HOME/.gradle" + # enable extra java logging mkdir -p /var/local/grpc_java_logging echo "handlers = java.util.logging.ConsoleHandler diff --git a/templates/tools/dockerfile/ruby_deps.include b/templates/tools/dockerfile/ruby_deps.include index c2d330988c6..bcbd08c29ea 100644 --- a/templates/tools/dockerfile/ruby_deps.include +++ b/templates/tools/dockerfile/ruby_deps.include @@ -2,7 +2,8 @@ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN apt-get update && apt-get install -y gnupg2 +RUN gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.5 @@ -11,4 +12,4 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.5" RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.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.5' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-document" +RUN /bin/bash -l -c "gem install bundler --no-document -v 1.9" diff --git a/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template index 01e22cce4c4..f65ed9e58b7 100644 --- a/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_jessie_x64/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template b/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template index b9cd1e98285..36f243c3405 100644 --- a/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_jessie_x86/Dockerfile.template @@ -15,6 +15,7 @@ # limitations under the License. FROM 32bit/debian:jessie + RUN sed -i '/deb http:\/\/http.debian.net\/debian jessie-updates main/d' /etc/apt/sources.list <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile.template index 6070330e919..7d173236ee3 100644 --- a/templates/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile.template @@ -16,6 +16,7 @@ # This is the base Docker image we use for running tests on RBE FROM gcr.io/cloud-marketplace/google/rbe-debian8@sha256:1ede2a929b44d629ec5abe86eee6d7ffea1d5a4d247489a8867d46cfde3e38bd + RUN sed -i '/deb http:\/\/httpredir.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/fuzzer/Dockerfile.template b/templates/tools/dockerfile/test/fuzzer/Dockerfile.template index 6dcd7b77dec..345da0804ad 100644 --- a/templates/tools/dockerfile/test/fuzzer/Dockerfile.template +++ b/templates/tools/dockerfile/test/fuzzer/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template index af85a542358..cd0513a1a4d 100644 --- a/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/node_jessie_x64/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template index 0b2290b741c..d29cd7e4e59 100644 --- a/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php7_jessie_x64/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../php7_deps.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template index fdbad53c391..3bd8f9c7c47 100644 --- a/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/php_jessie_x64/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template index e73b839a284..dde33a9e1a4 100644 --- a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template index bf4bb279182..2fed02246bb 100644 --- a/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/ruby_jessie_x64/Dockerfile.template @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:jessie + <%include file="../../debian_jessie_header.include"/> <%include file="../../apt_get_basic.include"/> <%include file="../../gcp_api_libraries.include"/> diff --git a/test/core/bad_connection/BUILD b/test/core/bad_connection/BUILD index 8ada933e796..82b38ccc469 100644 --- a/test/core/bad_connection/BUILD +++ b/test/core/bad_connection/BUILD @@ -29,4 +29,5 @@ grpc_cc_binary( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD index 57e5191af4c..a9cfa961ec2 100644 --- a/test/core/client_channel/BUILD +++ b/test/core/client_channel/BUILD @@ -52,6 +52,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -78,3 +79,17 @@ grpc_cc_test( "//test/core/util:grpc_test_util", ], ) + +grpc_cc_test( + name = "service_config_test", + srcs = ["service_config_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) diff --git a/test/core/client_channel/service_config_test.cc b/test/core/client_channel/service_config_test.cc new file mode 100644 index 00000000000..10cb4cd4404 --- /dev/null +++ b/test/core/client_channel/service_config_test.cc @@ -0,0 +1,365 @@ +/* + * + * Copyright 2019 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/gpr/string.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +namespace grpc_core { +namespace testing { + +class TestParsedObject1 : public ServiceConfigParsedObject { + public: + TestParsedObject1(int value) : value_(value) {} + + int value() const { return value_; } + + private: + int value_; +}; + +class TestParser1 : public ServiceConfigParser { + public: + UniquePtr ParseGlobalParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + for (grpc_json* field = json->child; field != nullptr; + field = field->next) { + if (strcmp(field->key, "global_param") == 0) { + if (field->type != GRPC_JSON_NUMBER) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage()); + return nullptr; + } + int value = gpr_parse_nonnegative_int(field->value); + if (value == -1) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage()); + return nullptr; + } + return UniquePtr( + New(value)); + } + } + return nullptr; + } + + static const char* InvalidTypeErrorMessage() { + return "global_param value type should be a number"; + } + + static const char* InvalidValueErrorMessage() { + return "global_param value type should be non-negative"; + } +}; + +class TestParser2 : public ServiceConfigParser { + public: + UniquePtr ParsePerMethodParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + for (grpc_json* field = json->child; field != nullptr; + field = field->next) { + if (field->key == nullptr || strcmp(field->key, "name") == 0) { + continue; + } + if (strcmp(field->key, "method_param") == 0) { + if (field->type != GRPC_JSON_NUMBER) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidTypeErrorMessage()); + return nullptr; + } + int value = gpr_parse_nonnegative_int(field->value); + if (value == -1) { + *error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING(InvalidValueErrorMessage()); + return nullptr; + } + return UniquePtr( + New(value)); + } + } + return nullptr; + } + + static const char* InvalidTypeErrorMessage() { + return "method_param value type should be a number"; + } + + static const char* InvalidValueErrorMessage() { + return "method_param value type should be non-negative"; + } +}; + +// This parser always adds errors +class ErrorParser : public ServiceConfigParser { + public: + UniquePtr ParsePerMethodParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError()); + return nullptr; + } + + UniquePtr ParseGlobalParams( + const grpc_json* json, grpc_error** error) override { + GPR_DEBUG_ASSERT(error != nullptr); + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError()); + return nullptr; + } + + static const char* MethodError() { return "ErrorParser : methodError"; } + + static const char* GlobalError() { return "ErrorParser : globalError"; } +}; + +class ServiceConfigTest : public ::testing::Test { + protected: + void SetUp() override { + ServiceConfig::Shutdown(); + ServiceConfig::Init(); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 0); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 1); + } +}; + +TEST_F(ServiceConfigTest, ErrorCheck1) { + const char* test_json = ""; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), + "failed to parse JSON for service config") != nullptr); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ServiceConfigTest, BasicTest1) { + const char* test_json = "{}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, ErrorNoNames) { + const char* test_json = "{\"methodConfig\": [{\"blah\":1}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ServiceConfigTest, ErrorNoNamesWithMultipleMethodConfigs) { + const char* test_json = + "{\"methodConfig\": [{}, {\"name\":[{\"service\":\"TestServ\"}]}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + EXPECT_TRUE(strstr(grpc_error_string(error), "No names found") != nullptr); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ServiceConfigTest, ValidMethodConfig) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}]}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + EXPECT_TRUE(error == GRPC_ERROR_NONE); +} + +TEST_F(ServiceConfigTest, Parser1BasicTest1) { + const char* test_json = "{\"global_param\":5}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error == GRPC_ERROR_NONE); + EXPECT_TRUE((static_cast( + svc_cfg->GetParsedGlobalServiceConfigObject(0))) + ->value() == 5); +} + +TEST_F(ServiceConfigTest, Parser1BasicTest2) { + const char* test_json = "{\"global_param\":1000}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error == GRPC_ERROR_NONE); + EXPECT_TRUE((static_cast( + svc_cfg->GetParsedGlobalServiceConfigObject(0))) + ->value() == 1000); +} + +TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { + const char* test_json = "{\"global_param\":\"5\"}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + TestParser1::InvalidTypeErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { + const char* test_json = "{\"global_param\":-5}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + TestParser1::InvalidValueErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ServiceConfigTest, Parser2BasicTest) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " + "\"method_param\":5}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error == GRPC_ERROR_NONE); + const auto* const* vector_ptr = svc_cfg->GetMethodServiceConfigObjectsVector( + grpc_slice_from_static_string("/TestServ/TestMethod")); + EXPECT_TRUE(vector_ptr != nullptr); + const auto* vector = *vector_ptr; + auto parsed_object = ((*vector)[1]).get(); + EXPECT_TRUE(static_cast(parsed_object)->value() == 5); +} + +TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " + "\"method_param\":\"5\"}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Method " + "Params)(.*)(referenced_errors)()(.*)(methodConfig)(" + ".*)(referenced_errors)(.*)") + + TestParser2::InvalidTypeErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { + const char* test_json = + "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " + "\"method_param\":-5}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Method " + "Params)(.*)(referenced_errors)()(.*)(methodConfig)(" + ".*)(referenced_errors)(.*)") + + TestParser2::InvalidValueErrorMessage()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); +} + +// Test parsing with ErrorParsers which always add errors +class ErroredParsersScopingTest : public ::testing::Test { + protected: + void SetUp() override { + ServiceConfig::Shutdown(); + ServiceConfig::Init(); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 0); + EXPECT_TRUE(ServiceConfig::RegisterParser( + UniquePtr(New())) == 1); + } +}; + +TEST_F(ErroredParsersScopingTest, GlobalParams) { + const char* test_json = "{}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e(std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + ErrorParser::GlobalError() + std::string("(.*)") + + ErrorParser::GlobalError()); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); +} + +TEST_F(ErroredParsersScopingTest, MethodParams) { + const char* test_json = "{\"methodConfig\": [{}]}"; + grpc_error* error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(test_json, &error); + ASSERT_TRUE(error != GRPC_ERROR_NONE); + gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + std::regex e( + std::string("(Service config parsing " + "error)(.*)(referenced_errors\":\\[)(.*)(Global " + "Params)(.*)(referenced_errors)()(.*)") + + ErrorParser::GlobalError() + std::string("(.*)") + + ErrorParser::GlobalError() + + std::string("(.*)(Method " + "Params)(.*)(referenced_errors)(.*)(field:methodConfig " + "error:No names " + "found)(.*)(methodConfig)(.*)(referenced_errors)(.*)") + + ErrorParser::MethodError() + std::string("(.*)") + + ErrorParser::MethodError() + std::string("(.*)(No names specified)")); + std::smatch match; + std::string s(grpc_error_string(error)); + EXPECT_TRUE(std::regex_search(s, match, e)); + GRPC_ERROR_UNREF(error); +} + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + grpc_init(); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index 79c079bcc73..10b9314a84a 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -31,7 +31,8 @@ def _fixture_options( is_http2 = True, supports_proxy_auth = False, supports_write_buffering = True, - client_channel = True): + client_channel = True, + supports_msvc = True): return struct( fullstack = fullstack, includes_proxy = includes_proxy, @@ -44,6 +45,7 @@ def _fixture_options( supports_proxy_auth = supports_proxy_auth, supports_write_buffering = supports_write_buffering, client_channel = client_channel, + supports_msvc = supports_msvc, #_platforms=_platforms, ) @@ -120,10 +122,11 @@ END2END_NOSEC_FIXTURES = { client_channel = False, secure = False, _platforms = ["linux", "mac", "posix"], + supports_msvc = False, ), "h2_full": _fixture_options(secure = False), - "h2_full+pipe": _fixture_options(secure = False, _platforms = ["linux"]), - "h2_full+trace": _fixture_options(secure = False, tracing = True), + "h2_full+pipe": _fixture_options(secure = False, _platforms = ["linux"], supports_msvc = False), + "h2_full+trace": _fixture_options(secure = False, tracing = True, supports_msvc = False), "h2_full+workarounds": _fixture_options(secure = False), "h2_http_proxy": _fixture_options(secure = False, supports_proxy_auth = True), "h2_proxy": _fixture_options(secure = False, includes_proxy = True), @@ -152,6 +155,7 @@ END2END_NOSEC_FIXTURES = { dns_resolver = False, _platforms = ["linux", "mac", "posix"], secure = False, + supports_msvc = False, ), } @@ -381,6 +385,7 @@ def grpc_end2end_tests(): ":proxy", ":local_util", ], + tags = ["no_windows"], ) for f, fopt in END2END_FIXTURES.items(): @@ -394,6 +399,7 @@ def grpc_end2end_tests(): "//:grpc", "//:gpr", ], + tags = ["no_windows"], ) for t, topt in END2END_TESTS.items(): #print(_compatible(fopt, topt), f, t, fopt, topt) @@ -409,6 +415,7 @@ def grpc_end2end_tests(): t, poller, ], + tags = ["no_windows"], ) def grpc_end2end_nosec_tests(): @@ -431,6 +438,7 @@ def grpc_end2end_nosec_tests(): ":proxy", ":local_util", ], + tags = ["no_windows"], ) for f, fopt in END2END_NOSEC_FIXTURES.items(): @@ -446,6 +454,7 @@ def grpc_end2end_nosec_tests(): "//:grpc_unsecure", "//:gpr", ], + tags = ["no_windows"], ) for t, topt in END2END_TESTS.items(): #print(_compatible(fopt, topt), f, t, fopt, topt) @@ -463,4 +472,5 @@ def grpc_end2end_nosec_tests(): t, poller, ], + tags = ["no_windows"], ) diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc index 9c018962f83..a8c57899e2c 100644 --- a/test/core/end2end/tests/simple_request.cc +++ b/test/core/end2end/tests/simple_request.cc @@ -86,6 +86,14 @@ static void end_test(grpc_end2end_test_fixture* f) { grpc_completion_queue_destroy(f->shutdown_cq); } +static void check_peer(char* peer_name) { + // If the peer name is a uds path, then check if it is filled + if (strncmp(peer_name, "unix:/", strlen("unix:/")) == 0) { + GPR_ASSERT(strncmp(peer_name, "unix:/tmp/grpc_fullstack_test.", + strlen("unix:/tmp/grpc_fullstack_test.")) == 0); + } +} + static void simple_request_body(grpc_end2end_test_config config, grpc_end2end_test_fixture f) { grpc_call* c; @@ -166,10 +174,12 @@ static void simple_request_body(grpc_end2end_test_config config, peer = grpc_call_get_peer(s); GPR_ASSERT(peer != nullptr); gpr_log(GPR_DEBUG, "server_peer=%s", peer); + check_peer(peer); gpr_free(peer); peer = grpc_call_get_peer(c); GPR_ASSERT(peer != nullptr); gpr_log(GPR_DEBUG, "client_peer=%s", peer); + check_peer(peer); gpr_free(peer); memset(ops, 0, sizeof(ops)); diff --git a/test/core/gprpp/BUILD b/test/core/gprpp/BUILD index c8d47be5bb2..4665827e10f 100644 --- a/test/core/gprpp/BUILD +++ b/test/core/gprpp/BUILD @@ -38,6 +38,19 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "grpc_core_map_test", + srcs = ["map_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr_base", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "memory_test", srcs = ["memory_test.cc"], diff --git a/test/core/gprpp/map_test.cc b/test/core/gprpp/map_test.cc new file mode 100644 index 00000000000..e70bf38f111 --- /dev/null +++ b/test/core/gprpp/map_test.cc @@ -0,0 +1,409 @@ +/* + * + * Copyright 2017 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "src/core/lib/gprpp/map.h" +#include +#include "include/grpc/support/string_util.h" +#include "src/core/lib/gprpp/inlined_vector.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/orphanable.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "test/core/util/test_config.h" + +namespace grpc_core { +namespace testing { +class Payload { + public: + Payload() : data_(-1) {} + explicit Payload(int data) : data_(data) {} + Payload(const Payload& other) : data_(other.data_) {} + Payload& operator=(const Payload& other) { + if (this != &other) { + data_ = other.data_; + } + return *this; + } + int data() { return data_; } + + private: + int data_; +}; + +inline UniquePtr CopyString(const char* string) { + return UniquePtr(gpr_strdup(string)); +} + +static constexpr char kKeys[][4] = {"abc", "efg", "hij", "klm", "xyz"}; + +class MapTest : public ::testing::Test { + public: + template + typename ::grpc_core::Map::Entry* Root( + typename ::grpc_core::Map* map) { + return map->root_; + } +}; + +// Test insertion of Payload +TEST_F(MapTest, EmplaceAndFind) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(kKeys[i])->second.data()); + } +} + +// Test insertion of Payload Unique Ptrs +TEST_F(MapTest, EmplaceAndFindWithUniquePtrValue) { + Map, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], MakeUnique(i)); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(kKeys[i])->second->data()); + } +} + +// Test insertion of Unique Ptr kKeys and Payload +TEST_F(MapTest, EmplaceAndFindWithUniquePtrKey) { + Map, Payload, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(CopyString(kKeys[i]), Payload(i)); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(CopyString(kKeys[i]))->second.data()); + } +} + +// Test insertion of Payload +TEST_F(MapTest, InsertAndFind) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.insert(MakePair(kKeys[i], Payload(i))); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(kKeys[i])->second.data()); + } +} + +// Test insertion of Payload Unique Ptrs +TEST_F(MapTest, InsertAndFindWithUniquePtrValue) { + Map, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.insert(MakePair(kKeys[i], MakeUnique(i))); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(kKeys[i])->second->data()); + } +} + +// Test insertion of Unique Ptr kKeys and Payload +TEST_F(MapTest, InsertAndFindWithUniquePtrKey) { + Map, Payload, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.insert(MakePair(CopyString(kKeys[i]), Payload(i))); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(CopyString(kKeys[i]))->second.data()); + } +} + +// Test bracket operators +TEST_F(MapTest, BracketOperator) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map[kKeys[i]] = Payload(i); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map[kKeys[i]].data()); + } +} + +// Test bracket operators with unique pointer to payload +TEST_F(MapTest, BracketOperatorWithUniquePtrValue) { + Map, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map[kKeys[i]] = MakeUnique(i); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map[kKeys[i]]->data()); + } +} + +// Test bracket operators with unique pointer to payload +TEST_F(MapTest, BracketOperatorWithUniquePtrKey) { + Map, Payload, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map[CopyString(kKeys[i])] = Payload(i); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map[CopyString(kKeys[i])].data()); + } +} + +// Test removal of a single value +TEST_F(MapTest, Erase) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + EXPECT_EQ(test_map.size(), 5UL); + EXPECT_EQ(test_map.erase(kKeys[3]), 1UL); // Remove "hij" + for (int i = 0; i < 5; i++) { + if (i == 3) { // "hij" should not be present + EXPECT_TRUE(test_map.find(kKeys[i]) == test_map.end()); + } else { + EXPECT_EQ(i, test_map.find(kKeys[i])->second.data()); + } + } + EXPECT_EQ(test_map.size(), 4UL); +} + +// Test removal of a single value with unique ptr to payload +TEST_F(MapTest, EraseWithUniquePtrValue) { + Map, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], MakeUnique(i)); + } + EXPECT_EQ(test_map.size(), 5UL); + test_map.erase(kKeys[3]); // Remove "hij" + for (int i = 0; i < 5; i++) { + if (i == 3) { // "hij" should not be present + EXPECT_TRUE(test_map.find(kKeys[i]) == test_map.end()); + } else { + EXPECT_EQ(i, test_map.find(kKeys[i])->second->data()); + } + } + EXPECT_EQ(test_map.size(), 4UL); +} + +// Test removal of a single value +TEST_F(MapTest, EraseWithUniquePtrKey) { + Map, Payload, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(CopyString(kKeys[i]), Payload(i)); + } + EXPECT_EQ(test_map.size(), 5UL); + test_map.erase(CopyString(kKeys[3])); // Remove "hij" + for (int i = 0; i < 5; i++) { + if (i == 3) { // "hij" should not be present + EXPECT_TRUE(test_map.find(CopyString(kKeys[i])) == test_map.end()); + } else { + EXPECT_EQ(i, test_map.find(CopyString(kKeys[i]))->second.data()); + } + } + EXPECT_EQ(test_map.size(), 4UL); +} + +// Test clear +TEST_F(MapTest, SizeAndClear) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + EXPECT_EQ(test_map.size(), 5UL); + EXPECT_FALSE(test_map.empty()); + test_map.clear(); + EXPECT_EQ(test_map.size(), 0UL); + EXPECT_TRUE(test_map.empty()); +} + +// Test clear with unique ptr payload +TEST_F(MapTest, SizeAndClearWithUniquePtrValue) { + Map, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], MakeUnique(i)); + } + EXPECT_EQ(test_map.size(), 5UL); + EXPECT_FALSE(test_map.empty()); + test_map.clear(); + EXPECT_EQ(test_map.size(), 0UL); + EXPECT_TRUE(test_map.empty()); +} + +// Test clear with unique ptr char key +TEST_F(MapTest, SizeAndClearWithUniquePtrKey) { + Map, Payload, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(CopyString(kKeys[i]), Payload(i)); + } + EXPECT_EQ(test_map.size(), 5UL); + EXPECT_FALSE(test_map.empty()); + test_map.clear(); + EXPECT_EQ(test_map.size(), 0UL); + EXPECT_TRUE(test_map.empty()); +} + +// Test correction of Left-Left Tree imbalance +TEST_F(MapTest, MapLL) { + Map test_map; + for (int i = 2; i >= 0; i--) { + test_map.emplace(kKeys[i], Payload(i)); + } + EXPECT_EQ(strcmp(Root(&test_map)->pair.first, kKeys[1]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->pair.first, kKeys[0]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->pair.first, kKeys[2]), 0); +} + +// Test correction of Left-Right tree imbalance +TEST_F(MapTest, MapLR) { + Map test_map; + int insertion_key_index[] = {2, 0, 1}; + for (int i = 0; i < 3; i++) { + int key_index = insertion_key_index[i]; + test_map.emplace(kKeys[key_index], Payload(key_index)); + } + EXPECT_EQ(strcmp(Root(&test_map)->pair.first, kKeys[1]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->pair.first, kKeys[0]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->pair.first, kKeys[2]), 0); +} + +// Test correction of Right-Left tree imbalance +TEST_F(MapTest, MapRL) { + Map test_map; + int insertion_key_index[] = {0, 2, 1}; + for (int i = 0; i < 3; i++) { + int key_index = insertion_key_index[i]; + test_map.emplace(kKeys[key_index], Payload(key_index)); + } + EXPECT_EQ(strcmp(Root(&test_map)->pair.first, kKeys[1]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->pair.first, kKeys[0]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->pair.first, kKeys[2]), 0); +} + +// Test correction of Right-Right tree imbalance +TEST_F(MapTest, MapRR) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + EXPECT_EQ(strcmp(Root(&test_map)->pair.first, kKeys[1]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->pair.first, kKeys[0]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->pair.first, kKeys[3]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->left->pair.first, kKeys[2]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->right->pair.first, kKeys[4]), 0); +} + +// Test correction after random insertion +TEST_F(MapTest, MapRandomInsertions) { + Map test_map; + int insertion_key_index[] = {1, 4, 3, 0, 2}; + for (int i = 0; i < 5; i++) { + int key_index = insertion_key_index[i]; + test_map.emplace(kKeys[key_index], Payload(key_index)); + } + EXPECT_EQ(strcmp(Root(&test_map)->pair.first, kKeys[3]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->pair.first, kKeys[1]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->right->pair.first, kKeys[4]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->right->pair.first, kKeys[2]), 0); + EXPECT_EQ(strcmp(Root(&test_map)->left->left->pair.first, kKeys[0]), 0); +} + +// Test Map iterator +TEST_F(MapTest, Iteration) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + int count = 0; + for (auto iter = test_map.begin(); iter != test_map.end(); iter++) { + EXPECT_EQ(iter->second.data(), count); + count++; + } + EXPECT_EQ(count, 5); +} + +// Test Map iterator with unique ptr payload +TEST_F(MapTest, IterationWithUniquePtrValue) { + Map, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], MakeUnique(i)); + } + int count = 0; + for (auto iter = test_map.begin(); iter != test_map.end(); iter++) { + EXPECT_EQ(iter->second->data(), count); + count++; + } + EXPECT_EQ(count, 5); +} + +// Test Map iterator with unique ptr to char key +TEST_F(MapTest, IterationWithUniquePtrKey) { + Map, Payload, StringLess> test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(CopyString(kKeys[i]), Payload(i)); + } + int count = 0; + for (auto iter = test_map.begin(); iter != test_map.end(); iter++) { + EXPECT_EQ(iter->second.data(), count); + count++; + } + EXPECT_EQ(count, 5); +} + +// Test removing entries while iterating the map +TEST_F(MapTest, EraseUsingIterator) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(kKeys[i], Payload(i)); + } + int count = 0; + for (auto iter = test_map.begin(); iter != test_map.end();) { + EXPECT_EQ(iter->second.data(), count); + iter = test_map.erase(iter); + count++; + } + EXPECT_EQ(count, 5); + EXPECT_TRUE(test_map.empty()); +} + +// Random ops on a Map with Integer key of Payload value, +// tests default comparator +TEST_F(MapTest, RandomOpsWithIntKey) { + Map test_map; + for (int i = 0; i < 5; i++) { + test_map.emplace(i, Payload(i)); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i, test_map.find(i)->second.data()); + } + for (int i = 0; i < 5; i++) { + test_map[i] = Payload(i + 10); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(i + 10, test_map[i].data()); + } + EXPECT_EQ(test_map.erase(3), 1UL); + EXPECT_TRUE(test_map.find(3) == test_map.end()); + EXPECT_FALSE(test_map.empty()); + EXPECT_EQ(test_map.size(), 4UL); + test_map.clear(); + EXPECT_EQ(test_map.size(), 0UL); + EXPECT_TRUE(test_map.empty()); +} + +} // namespace testing +} // namespace grpc_core + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD index b9d2f31515a..0824efb980f 100644 --- a/test/core/handshake/BUILD +++ b/test/core/handshake/BUILD @@ -32,6 +32,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_library( @@ -43,6 +44,7 @@ grpc_cc_library( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -60,6 +62,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -77,6 +80,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 5e4338aee37..1aefa0ab224 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -81,6 +81,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -92,6 +93,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -103,6 +105,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -139,6 +142,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -153,6 +157,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -214,6 +219,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -225,6 +231,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -237,6 +244,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -259,6 +267,7 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -303,4 +312,5 @@ grpc_cc_test( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) diff --git a/test/core/iomgr/socket_utils_test.cc b/test/core/iomgr/socket_utils_test.cc index 420873734de..f0537e03e9d 100644 --- a/test/core/iomgr/socket_utils_test.cc +++ b/test/core/iomgr/socket_utils_test.cc @@ -24,6 +24,7 @@ #include "src/core/lib/iomgr/socket_utils_posix.h" #include +#include #include #include diff --git a/test/core/network_benchmarks/BUILD b/test/core/network_benchmarks/BUILD index fbc611d5fe3..1194e4ad7bb 100644 --- a/test/core/network_benchmarks/BUILD +++ b/test/core/network_benchmarks/BUILD @@ -33,4 +33,5 @@ grpc_cc_binary( "//:grpc", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index 2a31763c73c..496f064439c 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -36,6 +36,10 @@ #include "src/core/tsi/transport_security.h" #include "test/core/util/test_config.h" +#ifndef TSI_OPENSSL_ALPN_SUPPORT +#define TSI_OPENSSL_ALPN_SUPPORT 1 +#endif + static int check_transport_security_type(const grpc_auth_context* ctx) { grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME); @@ -432,6 +436,43 @@ static void test_default_ssl_roots(void) { gpr_free(roots_env_var_file_path); } +static void test_peer_alpn_check(void) { +#if TSI_OPENSSL_ALPN_SUPPORT + tsi_peer peer; + const char* alpn = "grpc"; + const char* wrong_alpn = "wrong"; + // peer does not have a TSI_SSL_ALPN_SELECTED_PROTOCOL property. + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property("wrong peer property name", + alpn, strlen(alpn), + &peer.properties[0]) == TSI_OK); + grpc_error* error = grpc_ssl_check_alpn(&peer); + GPR_ASSERT(error != GRPC_ERROR_NONE); + tsi_peer_destruct(&peer); + GRPC_ERROR_UNREF(error); + // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property but with an incorrect + // property value. + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL, + wrong_alpn, strlen(wrong_alpn), + &peer.properties[0]) == TSI_OK); + error = grpc_ssl_check_alpn(&peer); + GPR_ASSERT(error != GRPC_ERROR_NONE); + tsi_peer_destruct(&peer); + GRPC_ERROR_UNREF(error); + // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property with a correct property + // value. + GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK); + GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL, + alpn, strlen(alpn), + &peer.properties[0]) == TSI_OK); + GPR_ASSERT(grpc_ssl_check_alpn(&peer) == GRPC_ERROR_NONE); + tsi_peer_destruct(&peer); +#else + GPR_ASSERT(grpc_ssl_check_alpn(nullptr) == GRPC_ERROR_NONE); +#endif +} + int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); grpc_init(); @@ -443,7 +484,7 @@ int main(int argc, char** argv) { test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); test_ipv6_address_san(); test_default_ssl_roots(); - + test_peer_alpn_check(); grpc_shutdown(); return 0; } diff --git a/test/core/util/BUILD b/test/core/util/BUILD index b931a9d683c..98e69c6ef34 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -76,17 +76,17 @@ grpc_cc_library( "tracer_util.h", "trickle_endpoint.h", ], + data = [ + "lsan_suppressions.txt", + "tsan_suppressions.txt", + "ubsan_suppressions.txt", + ], language = "C++", deps = [ ":grpc_debugger_macros", "//:gpr", "//:grpc_common", ], - data = [ - "lsan_suppressions.txt", - "tsan_suppressions.txt", - "ubsan_suppressions.txt", - ], ) grpc_cc_library( @@ -133,6 +133,7 @@ grpc_cc_library( ":grpc_test_util", "//:grpc", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/common/BUILD b/test/cpp/common/BUILD index 01699b26add..b67c1995ff7 100644 --- a/test/cpp/common/BUILD +++ b/test/cpp/common/BUILD @@ -28,6 +28,7 @@ grpc_cc_test( "//:grpc++_unsecure", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index 998ba8e1e4e..707a628148e 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -99,6 +99,7 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -633,6 +634,7 @@ grpc_cc_test( "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/end2end/cfstream_test.cc b/test/cpp/end2end/cfstream_test.cc index a6ed7c66d84..63d76e96f8b 100644 --- a/test/cpp/end2end/cfstream_test.cc +++ b/test/cpp/end2end/cfstream_test.cc @@ -62,7 +62,7 @@ class CFStreamTest : public ::testing::Test { CFStreamTest() : server_host_("grpctest"), interface_("lo0"), - ipv4_address_("127.0.0.2"), + ipv4_address_("10.0.0.1"), kRequestMessage_("🖖") {} void DNSUp() { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 421b31ad08a..f1aed093dc4 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -611,6 +611,18 @@ TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorLoggingTest) { EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20); } +TEST_F(ClientInterceptorsEnd2endTest, + LameChannelClientInterceptorHijackingTest) { + ChannelArguments args; + std::vector> + creators; + creators.push_back(std::unique_ptr( + new HijackingInterceptorFactory())); + auto channel = experimental::CreateCustomChannelWithInterceptors( + server_address_, nullptr, args, std::move(creators)); + MakeCall(channel); +} + TEST_F(ClientInterceptorsEnd2endTest, ClientInterceptorHijackingTest) { ChannelArguments args; DummyInterceptor::Reset(); diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index 4244690d76b..77f9db94acc 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -940,6 +940,32 @@ TEST_F(ClientLbEnd2endTest, PickFirstPendingUpdateAndSelectedSubchannelFails) { WaitForServer(stub, 1, DEBUG_LOCATION, true /* ignore_failure */); } +TEST_F(ClientLbEnd2endTest, PickFirstStaysIdleUponEmptyUpdate) { + // Start server, send RPC, and make sure channel is READY. + const int kNumServers = 1; + StartServers(kNumServers); + auto channel = BuildChannel(""); // pick_first is the default. + auto stub = BuildStub(channel); + SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); + // Stop server. Channel should go into state IDLE. + servers_[0]->Shutdown(); + EXPECT_TRUE(WaitForChannelNotReady(channel.get())); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_IDLE); + // Now send resolver update that includes no addresses. Channel + // should stay in state IDLE. + SetNextResolution({}); + EXPECT_FALSE(channel->WaitForStateChange( + GRPC_CHANNEL_IDLE, grpc_timeout_seconds_to_deadline(3))); + // Now bring the backend back up and send a non-empty resolver update, + // and then try to send an RPC. Channel should go back into state READY. + StartServer(0); + SetNextResolution(GetServersPorts()); + CheckRpcSendOk(stub, DEBUG_LOCATION); + EXPECT_EQ(channel->GetState(false), GRPC_CHANNEL_READY); +} + TEST_F(ClientLbEnd2endTest, RoundRobin) { // Start servers and send one RPC per server. const int kNumServers = 3; diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 40023c72f62..fb951fd44e6 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -1420,18 +1420,18 @@ TEST_P(End2endTest, DelayedRpcLateCanceledUsingCancelCallback) { EchoResponse response; request.set_message("Hello"); request.mutable_param()->set_skip_cancelled_check(true); - // Let server sleep for 80 ms first to give the cancellation a chance. - // This is split into 40 ms to start the cancel and 40 ms extra time for + // Let server sleep for 200 ms first to give the cancellation a chance. + // This is split into 100 ms to start the cancel and 100 ms extra time for // it to make it to the server, to make it highly probable that the server // RPC would have already started by the time the cancellation is sent // and the server-side gets enough time to react to it. - request.mutable_param()->set_server_sleep_us(80 * 1000); + request.mutable_param()->set_server_sleep_us(200000); std::thread echo_thread{[this, &context, &request, &response] { Status s = stub_->Echo(&context, request, &response); EXPECT_EQ(StatusCode::CANCELLED, s.error_code()); }}; - std::this_thread::sleep_for(std::chrono::microseconds(40000)); + std::this_thread::sleep_for(std::chrono::microseconds(100000)); context.TryCancel(); echo_thread.join(); } diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index 7c6432379a6..0dc3746c2d7 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -208,67 +208,74 @@ class BalancerServiceImpl : public BalancerService { client_load_reporting_interval_seconds) {} Status BalanceLoad(ServerContext* context, Stream* stream) override { - // Balancer shouldn't receive the call credentials metadata. - EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), - context->client_metadata().end()); gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); - LoadBalanceRequest request; - std::vector responses_and_delays; - - if (!stream->Read(&request)) { - goto done; - } - IncreaseRequestCount(); - gpr_log(GPR_INFO, "LB[%p]: received initial message '%s'", this, - request.DebugString().c_str()); - - // TODO(juanlishen): Initial response should always be the first response. - if (client_load_reporting_interval_seconds_ > 0) { - LoadBalanceResponse initial_response; - initial_response.mutable_initial_response() - ->mutable_client_stats_report_interval() - ->set_seconds(client_load_reporting_interval_seconds_); - stream->Write(initial_response); - } - { std::unique_lock lock(mu_); - responses_and_delays = responses_and_delays_; - } - for (const auto& response_and_delay : responses_and_delays) { - SendResponse(stream, response_and_delay.first, response_and_delay.second); + if (serverlist_done_) goto done; } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); - } + // Balancer shouldn't receive the call credentials metadata. + EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), + context->client_metadata().end()); + LoadBalanceRequest request; + std::vector responses_and_delays; + + if (!stream->Read(&request)) { + goto done; + } + IncreaseRequestCount(); + gpr_log(GPR_INFO, "LB[%p]: received initial message '%s'", this, + request.DebugString().c_str()); + + // TODO(juanlishen): Initial response should always be the first response. + if (client_load_reporting_interval_seconds_ > 0) { + LoadBalanceResponse initial_response; + initial_response.mutable_initial_response() + ->mutable_client_stats_report_interval() + ->set_seconds(client_load_reporting_interval_seconds_); + stream->Write(initial_response); + } + + { + std::unique_lock lock(mu_); + responses_and_delays = responses_and_delays_; + } + for (const auto& response_and_delay : responses_and_delays) { + SendResponse(stream, response_and_delay.first, + response_and_delay.second); + } + { + std::unique_lock lock(mu_); + serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + } - if (client_load_reporting_interval_seconds_ > 0) { - request.Clear(); - if (stream->Read(&request)) { - gpr_log(GPR_INFO, "LB[%p]: received client load report message '%s'", - this, request.DebugString().c_str()); - GPR_ASSERT(request.has_client_stats()); - // We need to acquire the lock here in order to prevent the notify_one - // below from firing before its corresponding wait is executed. - std::lock_guard lock(mu_); - client_stats_.num_calls_started += - request.client_stats().num_calls_started(); - client_stats_.num_calls_finished += - request.client_stats().num_calls_finished(); - client_stats_.num_calls_finished_with_client_failed_to_send += - request.client_stats() - .num_calls_finished_with_client_failed_to_send(); - client_stats_.num_calls_finished_known_received += - request.client_stats().num_calls_finished_known_received(); - for (const auto& drop_token_count : - request.client_stats().calls_finished_with_drop()) { - client_stats_ - .drop_token_counts[drop_token_count.load_balance_token()] += - drop_token_count.num_calls(); + if (client_load_reporting_interval_seconds_ > 0) { + request.Clear(); + if (stream->Read(&request)) { + gpr_log(GPR_INFO, "LB[%p]: received client load report message '%s'", + this, request.DebugString().c_str()); + GPR_ASSERT(request.has_client_stats()); + // We need to acquire the lock here in order to prevent the notify_one + // below from firing before its corresponding wait is executed. + std::lock_guard lock(mu_); + client_stats_.num_calls_started += + request.client_stats().num_calls_started(); + client_stats_.num_calls_finished += + request.client_stats().num_calls_finished(); + client_stats_.num_calls_finished_with_client_failed_to_send += + request.client_stats() + .num_calls_finished_with_client_failed_to_send(); + client_stats_.num_calls_finished_known_received += + request.client_stats().num_calls_finished_known_received(); + for (const auto& drop_token_count : + request.client_stats().calls_finished_with_drop()) { + client_stats_ + .drop_token_counts[drop_token_count.load_balance_token()] += + drop_token_count.num_calls(); + } + load_report_ready_ = true; + load_report_cond_.notify_one(); } - load_report_ready_ = true; - load_report_cond_.notify_one(); } } done: @@ -542,8 +549,10 @@ class GrpclbEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromAddressDataList(address_data); if (service_config_json != nullptr) { + grpc_error* error = GRPC_ERROR_NONE; result.service_config = - grpc_core::ServiceConfig::Create(service_config_json); + grpc_core::ServiceConfig::Create(service_config_json, &error); + GRPC_ERROR_UNREF(error); } response_generator_->SetResponse(std::move(result)); } @@ -1359,7 +1368,7 @@ class UpdatesTest : public GrpclbEnd2endTest { UpdatesTest() : GrpclbEnd2endTest(4, 3, 0) {} }; -TEST_F(UpdatesTest, UpdateBalancers) { +TEST_F(UpdatesTest, UpdateBalancersButKeepUsingOriginalBalancer) { SetNextResolutionAllBalancers(); const std::vector first_backend{GetBackendPorts()[0]}; const std::vector second_backend{GetBackendPorts()[1]}; @@ -1379,9 +1388,6 @@ TEST_F(UpdatesTest, UpdateBalancers) { // All 10 requests should have gone to the first backend. EXPECT_EQ(10U, backends_[0]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); // Balancer 0 got a single request. EXPECT_EQ(1U, balancers_[0]->service_.request_count()); // and sent a single response. @@ -1397,25 +1403,21 @@ TEST_F(UpdatesTest, UpdateBalancers) { SetNextResolution(addresses); gpr_log(GPR_INFO, "========= UPDATE 1 DONE =========="); - // Wait until update has been processed, as signaled by the second backend - // receiving a request. EXPECT_EQ(0U, backends_[1]->service_.request_count()); - WaitForBackend(1); - - backends_[1]->service_.ResetCounters(); - gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - CheckRpcSendOk(10); - gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); - // All 10 requests should have gone to the second backend. - EXPECT_EQ(10U, backends_[1]->service_.request_count()); + gpr_timespec deadline = gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(10000, GPR_TIMESPAN)); + // Send 10 seconds worth of RPCs + do { + CheckRpcSendOk(); + } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); + // The current LB call is still working, so grpclb continued using it to the + // first balancer, which doesn't assign the second backend. + EXPECT_EQ(0U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); EXPECT_EQ(1U, balancers_[0]->service_.request_count()); EXPECT_EQ(1U, balancers_[0]->service_.response_count()); - EXPECT_EQ(1U, balancers_[1]->service_.request_count()); - EXPECT_EQ(1U, balancers_[1]->service_.response_count()); + EXPECT_EQ(0U, balancers_[1]->service_.request_count()); + EXPECT_EQ(0U, balancers_[1]->service_.response_count()); EXPECT_EQ(0U, balancers_[2]->service_.request_count()); EXPECT_EQ(0U, balancers_[2]->service_.response_count()); } @@ -1526,9 +1528,6 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { EXPECT_EQ(20U, backends_[0]->service_.request_count()); EXPECT_EQ(0U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); // Balancer 0 got a single request. EXPECT_EQ(1U, balancers_[0]->service_.request_count()); // and sent a single response. @@ -1558,9 +1557,6 @@ TEST_F(UpdatesTest, UpdateBalancersDeadUpdate) { // All 10 requests should have gone to the second backend. EXPECT_EQ(10U, backends_[1]->service_.request_count()); - balancers_[0]->service_.NotifyDoneWithServerlists(); - balancers_[1]->service_.NotifyDoneWithServerlists(); - balancers_[2]->service_.NotifyDoneWithServerlists(); EXPECT_EQ(1U, balancers_[0]->service_.request_count()); EXPECT_EQ(1U, balancers_[0]->service_.response_count()); // The second balancer, published as part of the first update, may end up diff --git a/test/cpp/end2end/test_service_impl.cc b/test/cpp/end2end/test_service_impl.cc index abbb669cf5c..048715300ad 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -143,7 +143,6 @@ void LoopUntilCancelled(Alarm* alarm, ServerContext* context, Status TestServiceImpl::Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) { - gpr_log(GPR_DEBUG, "Request message was %s", request->message().c_str()); // A bit of sleep to make sure that short deadline tests fail if (request->has_param() && request->param().server_sleep_us() > 0) { gpr_sleep_until( @@ -590,8 +589,9 @@ CallbackTestServiceImpl::RequestStream() { public: Reactor() {} void OnStarted(ServerContext* context, EchoResponse* response) override { - ctx_ = context; - response_ = response; + // Assign ctx_ and response_ as late as possible to increase likelihood of + // catching any races + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the // value: @@ -603,22 +603,26 @@ CallbackTestServiceImpl::RequestStream() { server_try_cancel_ = GetIntValueFromMetadata( kServerTryCancelRequest, context->client_metadata(), DO_NOT_CANCEL); - response_->set_message(""); + response->set_message(""); if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { - ServerTryCancelNonblocking(ctx_); - return; - } - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx_->TryCancel(); - // Don't wait for it here + ServerTryCancelNonblocking(context); + ctx_ = context; + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + context->TryCancel(); + // Don't wait for it here + } + ctx_ = context; + response_ = response; + StartRead(&request_); } - StartRead(&request_); + on_started_done_ = true; } void OnDone() override { delete this; } void OnCancel() override { + EXPECT_TRUE(on_started_done_); EXPECT_TRUE(ctx_->IsCancelled()); FinishOnce(Status::CANCELLED); } @@ -658,6 +662,7 @@ CallbackTestServiceImpl::RequestStream() { int server_try_cancel_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; @@ -674,8 +679,9 @@ CallbackTestServiceImpl::ResponseStream() { Reactor() {} void OnStarted(ServerContext* context, const EchoRequest* request) override { - ctx_ = context; - request_ = request; + // Assign ctx_ and request_ as late as possible to increase likelihood of + // catching any races + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the // value: @@ -692,19 +698,23 @@ CallbackTestServiceImpl::ResponseStream() { kServerResponseStreamsToSend, context->client_metadata(), kServerDefaultResponseStreamsToSend); if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { - ServerTryCancelNonblocking(ctx_); - return; - } - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx_->TryCancel(); - } - if (num_msgs_sent_ < server_responses_to_send_) { - NextWrite(); + ServerTryCancelNonblocking(context); + ctx_ = context; + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + context->TryCancel(); + } + ctx_ = context; + request_ = request; + if (num_msgs_sent_ < server_responses_to_send_) { + NextWrite(); + } } + on_started_done_ = true; } void OnDone() override { delete this; } void OnCancel() override { + EXPECT_TRUE(on_started_done_); EXPECT_TRUE(ctx_->IsCancelled()); FinishOnce(Status::CANCELLED); } @@ -754,6 +764,7 @@ CallbackTestServiceImpl::ResponseStream() { int server_responses_to_send_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; } @@ -765,7 +776,9 @@ CallbackTestServiceImpl::BidiStream() { public: Reactor() {} void OnStarted(ServerContext* context) override { - ctx_ = context; + // Assign ctx_ as late as possible to increase likelihood of catching any + // races + // If 'server_try_cancel' is set in the metadata, the RPC is cancelled by // the server by calling ServerContext::TryCancel() depending on the // value: @@ -779,18 +792,20 @@ CallbackTestServiceImpl::BidiStream() { server_write_last_ = GetIntValueFromMetadata( kServerFinishAfterNReads, context->client_metadata(), 0); if (server_try_cancel_ == CANCEL_BEFORE_PROCESSING) { - ServerTryCancelNonblocking(ctx_); - return; - } - - if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { - ctx_->TryCancel(); + ServerTryCancelNonblocking(context); + ctx_ = context; + } else { + if (server_try_cancel_ == CANCEL_DURING_PROCESSING) { + context->TryCancel(); + } + ctx_ = context; + StartRead(&request_); } - - StartRead(&request_); + on_started_done_ = true; } void OnDone() override { delete this; } void OnCancel() override { + EXPECT_TRUE(on_started_done_); EXPECT_TRUE(ctx_->IsCancelled()); FinishOnce(Status::CANCELLED); } @@ -840,6 +855,7 @@ CallbackTestServiceImpl::BidiStream() { int server_write_last_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 61e759c61b5..c767a4485ce 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -207,6 +207,10 @@ class BalancerServiceImpl : public BalancerService { Status BalanceLoad(ServerContext* context, Stream* stream) override { // TODO(juanlishen): Clean up the scoping. gpr_log(GPR_INFO, "LB[%p]: BalanceLoad", this); + { + std::unique_lock lock(mu_); + if (serverlist_done_) goto done; + } { // Balancer shouldn't receive the call credentials metadata. EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), @@ -524,8 +528,10 @@ class XdsEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromPortList(ports); if (service_config_json != nullptr) { + grpc_error* error = GRPC_ERROR_NONE; result.service_config = - grpc_core::ServiceConfig::Create(service_config_json); + grpc_core::ServiceConfig::Create(service_config_json, &error); + GRPC_ERROR_UNREF(error); } grpc_arg arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg( lb_channel_response_generator == nullptr @@ -555,8 +561,10 @@ class XdsEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromPortList(ports); if (service_config_json != nullptr) { + grpc_error* error = GRPC_ERROR_NONE; result.service_config = - grpc_core::ServiceConfig::Create(service_config_json); + grpc_core::ServiceConfig::Create(service_config_json, &error); + GRPC_ERROR_UNREF(error); } if (lb_channel_response_generator == nullptr) { lb_channel_response_generator = lb_channel_response_generator_.get(); @@ -860,25 +868,16 @@ TEST_F(SingleBalancerTest, AllServersUnreachableFailFast) { TEST_F(SingleBalancerTest, BackendsRestart) { SetNextResolution({}, kDefaultServiceConfig_.c_str()); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcsPerAddress = 100; ScheduleResponseForBalancer( 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts(), {}), 0); - // Make sure that trying to connect works without a call. - channel_->GetState(true /* try_to_connect */); - // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * num_backends_); - balancers_[0]->service_.NotifyDoneWithServerlists(); - // The balancer got a single request. - EXPECT_EQ(1U, balancers_[0]->service_.request_count()); - // and sent a single response. - EXPECT_EQ(1U, balancers_[0]->service_.response_count()); + WaitForAllBackends(); // Stop backends. RPCs should fail. ShutdownAllBackends(); CheckRpcSendFailure(); // Restart all backends. RPCs should start succeeding again. StartAllBackends(); - CheckRpcSendOk(1 /* times */, 1000 /* timeout_ms */, + CheckRpcSendOk(1 /* times */, 2000 /* timeout_ms */, true /* wait_for_ready */); } diff --git a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc index 73394028309..0638c3343e6 100644 --- a/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc +++ b/test/cpp/ext/filters/census/stats_plugin_end2end_test.cc @@ -25,6 +25,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "include/grpc++/grpc++.h" +#include "include/grpcpp/opencensus.h" #include "opencensus/stats/stats.h" #include "opencensus/stats/testing/test_utils.h" #include "src/cpp/ext/filters/census/grpc_plugin.h" diff --git a/test/cpp/interop/BUILD b/test/cpp/interop/BUILD index f36494d98db..6cf4719c17b 100644 --- a/test/cpp/interop/BUILD +++ b/test/cpp/interop/BUILD @@ -161,4 +161,5 @@ grpc_cc_test( "//test/cpp/util:test_config", "//test/cpp/util:test_util", ], + tags = ["no_windows"], ) diff --git a/test/cpp/interop/interop_test.cc b/test/cpp/interop/interop_test.cc index ae155b65f95..8e45b877212 100644 --- a/test/cpp/interop/interop_test.cc +++ b/test/cpp/interop/interop_test.cc @@ -16,10 +16,6 @@ * */ -#ifndef _POSIX_SOURCE -#define _POSIX_SOURCE -#endif - #include #include #include diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD index 70b4000780c..6e844a6dc62 100644 --- a/test/cpp/microbenchmarks/BUILD +++ b/test/cpp/microbenchmarks/BUILD @@ -45,6 +45,7 @@ grpc_cc_library( "//test/core/util:grpc_test_util_unsecure", "//test/cpp/util:test_config", ], + tags = ["no_windows"], ) grpc_cc_binary( @@ -52,6 +53,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_closure.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -59,6 +61,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_alarm.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -66,6 +69,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_arena.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -73,6 +77,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_byte_buffer.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -80,6 +85,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_channel.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -87,6 +93,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_call_create.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -94,6 +101,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_cq.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -101,6 +109,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_cq_multiple_threads.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -108,6 +117,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_error.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_library( @@ -117,6 +127,7 @@ grpc_cc_library( "fullstack_streaming_ping_pong.h", ], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -126,6 +137,7 @@ grpc_cc_binary( "bm_fullstack_streaming_ping_pong.cc", ], deps = [":fullstack_streaming_ping_pong_h"], + tags = ["no_windows"], ) grpc_cc_library( @@ -144,6 +156,7 @@ grpc_cc_binary( "bm_fullstack_streaming_pump.cc", ], deps = [":fullstack_streaming_pump_h"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -151,6 +164,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_fullstack_trickle.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_library( @@ -169,6 +183,7 @@ grpc_cc_binary( "bm_fullstack_unary_ping_pong.cc", ], deps = [":fullstack_unary_ping_pong_h"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -176,6 +191,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_metadata.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -183,6 +199,7 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_chttp2_hpack.cc"], deps = [":helpers"], + tags = ["no_windows"], ) grpc_cc_binary( @@ -202,4 +219,5 @@ grpc_cc_binary( testonly = 1, srcs = ["bm_timer.cc"], deps = [":helpers"], + tags = ["no_windows"], ) diff --git a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc index 9d42eb891df..4f4884bef9b 100644 --- a/test/cpp/microbenchmarks/bm_opencensus_plugin.cc +++ b/test/cpp/microbenchmarks/bm_opencensus_plugin.cc @@ -23,13 +23,17 @@ #include "absl/base/call_once.h" #include "absl/strings/str_cat.h" #include "include/grpc++/grpc++.h" +#include "include/grpcpp/opencensus.h" #include "opencensus/stats/stats.h" #include "src/cpp/ext/filters/census/grpc_plugin.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/cpp/microbenchmarks/helpers.h" +using ::grpc::RegisterOpenCensusPlugin; +using ::grpc::RegisterOpenCensusViewsForExport; + absl::once_flag once; -void RegisterOnce() { absl::call_once(once, grpc::RegisterOpenCensusPlugin); } +void RegisterOnce() { absl::call_once(once, RegisterOpenCensusPlugin); } class EchoServer final : public grpc::testing::EchoTestService::Service { grpc::Status Echo(grpc::ServerContext* context, @@ -99,7 +103,7 @@ static void BM_E2eLatencyCensusEnabled(benchmark::State& state) { RegisterOnce(); // This we can safely repeat, and doing so clears accumulated data to avoid // initialization costs varying between runs. - grpc::RegisterOpenCensusViewsForExport(); + RegisterOpenCensusViewsForExport(); EchoServerThread server; std::unique_ptr stub = diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index 78ad49ec984..bd685632c33 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -52,6 +52,7 @@ #ifndef GPR_WINDOWS #include +#include #include #endif diff --git a/test/cpp/naming/generate_resolver_component_tests.bzl b/test/cpp/naming/generate_resolver_component_tests.bzl index f36021560c1..589176762e6 100755 --- a/test/cpp/naming/generate_resolver_component_tests.bzl +++ b/test/cpp/naming/generate_resolver_component_tests.bzl @@ -33,6 +33,7 @@ def generate_resolver_component_tests(): "//:gpr", "//test/cpp/util:test_config", ], + tags = ["no_windows"], ) # meant to be invoked only through the top-level shell script driver grpc_cc_binary( @@ -52,6 +53,7 @@ def generate_resolver_component_tests(): "//:gpr", "//test/cpp/util:test_config", ], + tags = ["no_windows"], ) grpc_cc_test( name = "resolver_component_tests_runner_invoker%s" % unsecure_build_config_suffix, @@ -77,5 +79,6 @@ def generate_resolver_component_tests(): args = [ "--test_bin_name=resolver_component_test%s" % unsecure_build_config_suffix, "--running_under_bazel=true", - ] + ], + tags = ["no_windows"], ) diff --git a/test/cpp/naming/resolver_component_tests_runner_invoker.cc b/test/cpp/naming/resolver_component_tests_runner_invoker.cc index 68be00a67d6..d8f7100a284 100644 --- a/test/cpp/naming/resolver_component_tests_runner_invoker.cc +++ b/test/cpp/naming/resolver_component_tests_runner_invoker.cc @@ -29,6 +29,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #include "test/cpp/util/subprocess.h" #include "test/cpp/util/test_config.h" diff --git a/test/cpp/performance/BUILD b/test/cpp/performance/BUILD index 4fe95d5905e..6068c33f95f 100644 --- a/test/cpp/performance/BUILD +++ b/test/cpp/performance/BUILD @@ -31,4 +31,5 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_base", ], + tags = ["no_windows"], ) diff --git a/test/cpp/qps/json_run_localhost.cc b/test/cpp/qps/json_run_localhost.cc index 948c3088e67..42cc9e0ed76 100644 --- a/test/cpp/qps/json_run_localhost.cc +++ b/test/cpp/qps/json_run_localhost.cc @@ -24,6 +24,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #include #include "src/core/lib/gpr/env.h" diff --git a/test/cpp/qps/qps_benchmark_script.bzl b/test/cpp/qps/qps_benchmark_script.bzl index 855caa0d37c..b4767ec8e09 100644 --- a/test/cpp/qps/qps_benchmark_script.bzl +++ b/test/cpp/qps/qps_benchmark_script.bzl @@ -75,5 +75,6 @@ def json_run_localhost_batch(): ], tags = [ "json_run_localhost", + "no_windows", ], ) diff --git a/test/cpp/server/BUILD b/test/cpp/server/BUILD index 050b83f5c4f..a4811031691 100644 --- a/test/cpp/server/BUILD +++ b/test/cpp/server/BUILD @@ -29,6 +29,7 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -42,6 +43,7 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) grpc_cc_test( @@ -55,4 +57,5 @@ grpc_cc_test( "//src/proto/grpc/testing:echo_proto", "//test/core/util:grpc_test_util_unsecure", ], + tags = ["no_windows"], ) diff --git a/test/cpp/server/load_reporter/BUILD b/test/cpp/server/load_reporter/BUILD index 8d876c56d29..db5c93263ad 100644 --- a/test/cpp/server/load_reporter/BUILD +++ b/test/cpp/server/load_reporter/BUILD @@ -45,6 +45,7 @@ grpc_cc_test( "//:lb_server_load_reporting_filter", "//test/core/util:grpc_test_util", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/util/proto_reflection_descriptor_database.cc b/test/cpp/util/proto_reflection_descriptor_database.cc index 119272ca42e..d0c1a847253 100644 --- a/test/cpp/util/proto_reflection_descriptor_database.cc +++ b/test/cpp/util/proto_reflection_descriptor_database.cc @@ -44,14 +44,17 @@ ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() { Status status = stream_->Finish(); if (!status.ok()) { if (status.error_code() == StatusCode::UNIMPLEMENTED) { - gpr_log(GPR_INFO, + fprintf(stderr, "Reflection request not implemented; " - "is the ServerReflection service enabled?"); + "is the ServerReflection service enabled?\n"); + } else { + fprintf(stderr, + "ServerReflectionInfo rpc failed. Error code: %d, message: %s, " + "debug info: %s\n", + static_cast(status.error_code()), + status.error_message().c_str(), + ctx_.debug_error_string().c_str()); } - gpr_log(GPR_INFO, - "ServerReflectionInfo rpc failed. Error code: %d, details: %s", - static_cast(status.error_code()), - status.error_message().c_str()); } } } diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 0cf75f1e5f1..49688e5cf9b 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -24,6 +24,7 @@ #include #include +#include #include "test/core/end2end/data/ssl_test_data.h" diff --git a/test/distrib/cpp/run_distrib_test_cmake.sh b/test/distrib/cpp/run_distrib_test_cmake.sh index bada14d81c4..f3362f1cee7 100755 --- a/test/distrib/cpp/run_distrib_test_cmake.sh +++ b/test/distrib/cpp/run_distrib_test_cmake.sh @@ -17,7 +17,9 @@ set -ex cd "$(dirname "$0")/../../.." -echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list apt-get update apt-get install -t jessie-backports -y libssl-dev @@ -63,4 +65,3 @@ mkdir -p cmake/build cd cmake/build cmake ../.. make - diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh index 163527fbd50..ee1e0e8337d 100755 --- a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh +++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh @@ -17,7 +17,9 @@ set -ex cd "$(dirname "$0")/../../.." -echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list apt-get update apt-get install -t jessie-backports -y libssl-dev @@ -38,4 +40,3 @@ mkdir -p cmake/build cd cmake/build cmake ../.. make - diff --git a/test/distrib/csharp/DistribTest/DistribTest.csproj b/test/distrib/csharp/DistribTest/DistribTest.csproj index d18bb05be68..e3fc94b4f23 100644 --- a/test/distrib/csharp/DistribTest/DistribTest.csproj +++ b/test/distrib/csharp/DistribTest/DistribTest.csproj @@ -1,6 +1,7 @@  + Debug AnyCPU @@ -93,21 +94,30 @@ ..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll + + ..\packages\Google.Protobuf.3.7.0\lib\net45\Google.Protobuf.dll + + + + + 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}. + + /usr/lib/mono/4.5-api diff --git a/test/distrib/csharp/DistribTest/Program.cs b/test/distrib/csharp/DistribTest/Program.cs index 376add6b7b5..0ea7211fc45 100644 --- a/test/distrib/csharp/DistribTest/Program.cs +++ b/test/distrib/csharp/DistribTest/Program.cs @@ -25,6 +25,9 @@ namespace TestGrpcPackage { public static void Main(string[] args) { + // test codegen works + var reply = new Testcodegen.HelloReply(); + // This code doesn't do much but makes sure the native extension is loaded // which is what we are testing here. Channel c = new Channel("127.0.0.1:1000", ChannelCredentials.Insecure); diff --git a/test/distrib/csharp/DistribTest/packages.config b/test/distrib/csharp/DistribTest/packages.config index 134add7504d..5e09d5dad01 100644 --- a/test/distrib/csharp/DistribTest/packages.config +++ b/test/distrib/csharp/DistribTest/packages.config @@ -8,6 +8,7 @@ + \ No newline at end of file diff --git a/test/distrib/csharp/DistribTest/testcodegen.proto b/test/distrib/csharp/DistribTest/testcodegen.proto new file mode 100644 index 00000000000..7845ac92c49 --- /dev/null +++ b/test/distrib/csharp/DistribTest/testcodegen.proto @@ -0,0 +1,29 @@ +// Copyright 2019 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package testcodegen; + +service Greeter { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +message HelloRequest { + string name = 1; +} + +message HelloReply { + string message = 1; +} diff --git a/test/distrib/csharp/run_distrib_test.sh b/test/distrib/csharp/run_distrib_test.sh index 61924b91df8..45911cd91a7 100755 --- a/test/distrib/csharp/run_distrib_test.sh +++ b/test/distrib/csharp/run_distrib_test.sh @@ -24,7 +24,7 @@ unzip -o "$EXTERNAL_GIT_ROOT/input_artifacts/csharp_nugets_windows_dotnetcli.zip # Retry "nuget restore" to work around https://github.com/grpc/grpc/issues/16312 nuget restore || nuget restore || nuget restore -xbuild DistribTest.sln +msbuild DistribTest.sln mono DistribTest/bin/Debug/DistribTest.exe diff --git a/third_party/cares/cares.BUILD b/third_party/cares/cares.BUILD index 66ec1746122..78a4590c3e0 100644 --- a/third_party/cares/cares.BUILD +++ b/third_party/cares/cares.BUILD @@ -144,6 +144,7 @@ cc_library( "ares_strdup.h", "ares_strsplit.h", "ares_version.h", + "ares_writev.h", "bitncmp.h", "config-win32.h", "nameser.h", diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index 943690a2efd..5ee528d5d46 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -28,6 +28,36 @@ alias( actual = ":rbe_ubuntu1604_r346485_large", ) +alias( + name = "rbe_windows", + actual = ":rbe_windows_1803", +) + +# RBE Windows +platform( + name = "rbe_windows_1803", + constraint_values = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + "@bazel_tools//tools/cpp:msvc", + ], + remote_execution_properties = """ + properties: { + name: "container-image" + value:"docker://gcr.io/grpc-testing/rbe_windows_toolchain@sha256:689b177e4a157c431c7077d19d043de27922c37de835031f29c9093b8d5c6370" + } + properties: { + name: "gceMachineType" # Small machines for majority of tests. + value: "n1-highmem-2" + } + properties:{ + name: "OSFamily" + value: "Windows" + } + + """, +) + # RBE Ubuntu16_04 r346485 platform( name = "rbe_ubuntu1604_r346485", diff --git a/third_party/toolchains/bazel_0.23.2_rbe_windows/BUILD b/third_party/toolchains/bazel_0.23.2_rbe_windows/BUILD new file mode 100644 index 00000000000..5ce4e00c866 --- /dev/null +++ b/third_party/toolchains/bazel_0.23.2_rbe_windows/BUILD @@ -0,0 +1,188 @@ +# Copyright 2018 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This becomes the BUILD file for @local_config_cc// under Windows. +licenses(["notice"]) # Apache v2 + +package(default_visibility = ["//visibility:public"]) + +load(":cc_toolchain_config.bzl", "cc_toolchain_config") + +cc_library( + name = "malloc", +) + +filegroup( + name = "empty", + srcs = [], +) + +# Hardcoded toolchain, legacy behaviour. +cc_toolchain_suite( + name = "toolchain", + toolchains = { + "armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a", + "x64_windows|msvc-cl": ":cc-compiler-x64_windows", + "x64_windows|msys-gcc": ":cc-compiler-x64_windows_msys", + "x64_windows|mingw-gcc": ":cc-compiler-x64_windows_mingw", + "x64_windows_msys": ":cc-compiler-x64_windows_msys", + "x64_windows": ":cc-compiler-x64_windows", + "armeabi-v7a": ":cc-compiler-armeabi-v7a", + }, +) + +cc_toolchain( + name = "cc-compiler-x64_windows_msys", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":msys_x64", + toolchain_identifier = "msys_x64", +) + +cc_toolchain_config( + name = "msys_x64", + compiler = "msys-gcc", + cpu = "x64_windows", +) + +toolchain( + name = "cc-toolchain-x64_windows_msys", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + "@bazel_tools//tools/cpp:msys", + ], + target_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + toolchain = ":cc-compiler-x64_windows_msys", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain( + name = "cc-compiler-x64_windows_mingw", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 0, + toolchain_config = ":msys_x64_mingw", + toolchain_identifier = "msys_x64_mingw", +) + +cc_toolchain_config( + name = "msys_x64_mingw", + compiler = "mingw-gcc", + cpu = "x64_windows", +) + +toolchain( + name = "cc-toolchain-x64_windows_mingw", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + "@bazel_tools//tools/cpp:mingw", + ], + target_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + toolchain = ":cc-compiler-x64_windows_mingw", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain( + name = "cc-compiler-x64_windows", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":msvc_x64", + toolchain_identifier = "msvc_x64", +) + +cc_toolchain_config( + name = "msvc_x64", + compiler = "msvc-cl", + cpu = "x64_windows", +) + +toolchain( + name = "cc-toolchain-x64_windows", + exec_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + target_compatible_with = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:windows", + ], + toolchain = ":cc-compiler-x64_windows", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain( + name = "cc-compiler-armeabi-v7a", + all_files = ":empty", + ar_files = ":empty", + as_files = ":empty", + compiler_files = ":empty", + dwp_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":stub_armeabi-v7a", + toolchain_identifier = "stub_armeabi-v7a", +) + +cc_toolchain_config( + name = "stub_armeabi-v7a", + compiler = "compiler", + cpu = "armeabi-v7a", +) + +toolchain( + name = "cc-toolchain-armeabi-v7a", + exec_compatible_with = [ + ], + target_compatible_with = [ + "@bazel_tools//platforms:arm", + "@bazel_tools//platforms:android", + ], + toolchain = ":cc-compiler-armeabi-v7a", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +filegroup( + name = "link_dynamic_library", + srcs = ["link_dynamic_library.sh"], +) diff --git a/third_party/toolchains/bazel_0.23.2_rbe_windows/cc_toolchain_config.bzl b/third_party/toolchains/bazel_0.23.2_rbe_windows/cc_toolchain_config.bzl new file mode 100644 index 00000000000..790ddcb0947 --- /dev/null +++ b/third_party/toolchains/bazel_0.23.2_rbe_windows/cc_toolchain_config.bzl @@ -0,0 +1,1704 @@ +# Copyright 2019 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""A Starlark cc_toolchain configuration rule""" + +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "action_config", + "artifact_name_pattern", + "env_entry", + "env_set", + "feature", + "feature_set", + "flag_group", + "flag_set", + "make_variable", + "tool", + "tool_path", + "variable_with_value", + "with_feature_set", +) +load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") + +all_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, + ACTION_NAMES.lto_backend, +] + +all_cpp_compile_actions = [ + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.clif_match, +] + +preprocessor_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.clif_match, +] + +codegen_compile_actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, +] + +all_link_actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, +] + +def _windows_msvc_impl(ctx): + toolchain_identifier = "msvc_x64" + host_system_name = "local" + target_system_name = "local" + target_cpu = "x64_windows" + target_libc = "msvcrt" + compiler = "msvc-cl" + abi_version = "local" + abi_libc_version = "local" + cc_target_os = None + builtin_sysroot = None + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + "c:/tools/msys64/usr/", + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE", + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt", + ] + + cpp_link_nodeps_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "default_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe")], + ) + + cpp_link_static_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_static_library, + implies = [ + "nologo", + "archiver_flags", + "input_param_flags", + "linker_param_file", + "msvc_env", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/lib.exe")], + ) + + assemble_action = action_config( + action_name = ACTION_NAMES.assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/ml64.exe")], + ) + + preprocess_assemble_action = action_config( + action_name = ACTION_NAMES.preprocess_assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/ml64.exe")], + ) + + c_compile_action = action_config( + action_name = ACTION_NAMES.c_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "default_compile_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe")], + ) + + cpp_compile_action = action_config( + action_name = ACTION_NAMES.cpp_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "default_compile_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe")], + ) + + cpp_link_executable_action = action_config( + action_name = ACTION_NAMES.cpp_link_executable, + implies = [ + "nologo", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "default_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe")], + ) + + cpp_link_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "default_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe")], + ) + + action_configs = [ + assemble_action, + preprocess_assemble_action, + c_compile_action, + cpp_compile_action, + cpp_link_executable_action, + cpp_link_dynamic_library_action, + cpp_link_nodeps_dynamic_library_action, + cpp_link_static_library_action, + ] + + msvc_link_env_feature = feature( + name = "msvc_link_env", + env_sets = [ + env_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + env_entries = [env_entry(key = "LIB", value = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\LIB\\amd64;C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.10240.0\\ucrt\\x64;C:\\Program Files (x86)\\Windows Kits\\8.1\\lib\\winv6.3\\um\\x64;")], + ), + ], + ) + + shared_flag_feature = feature( + name = "shared_flag", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["/DLL"])], + ), + ], + ) + + determinism_feature = feature( + name = "determinism", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "/wd4117", + "-D__DATE__=\"redacted\"", + "-D__TIMESTAMP__=\"redacted\"", + "-D__TIME__=\"redacted\"", + ], + ), + ], + ), + ], + ) + + sysroot_feature = feature( + name = "sysroot", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + iterate_over = "sysroot", + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["%{unfiltered_compile_flags}"], + iterate_over = "unfiltered_compile_flags", + expand_if_available = "unfiltered_compile_flags", + ), + ], + ), + ], + ) + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + input_param_flags_feature = feature( + name = "input_param_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["/IMPLIB:%{interface_library_output_path}"], + expand_if_available = "interface_library_output_path", + ), + ], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{libopts}"], + iterate_over = "libopts", + expand_if_available = "libopts", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link", + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link.object_files", + flag_groups = [flag_group(flags = ["%{libraries_to_link.object_files}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "interface_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["/WHOLEARCHIVE:%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "static_library", + ), + ), + ], + expand_if_available = "libraries_to_link", + ), + ], + ), + ], + ) + + fastbuild_feature = feature( + name = "fastbuild", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEBUG:FASTLINK", "/INCREMENTAL:NO"], + ), + ], + ), + ], + implies = ["generate_pdb_file"], + ) + + user_compile_flags_feature = feature( + name = "user_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + archiver_flags_feature = feature( + name = "archiver_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/MACHINE:X64"])], + ), + ], + ) + + static_link_msvcrt_feature = feature(name = "static_link_msvcrt") + + dynamic_link_msvcrt_debug_feature = feature( + name = "dynamic_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MDd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + dbg_feature = feature( + name = "dbg", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEBUG:FULL", "/INCREMENTAL:NO"], + ), + ], + ), + ], + implies = ["generate_pdb_file"], + ) + + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/O2"])], + ), + ], + implies = ["frame_pointer"], + ) + + supports_interface_shared_libraries_feature = feature( + name = "supports_interface_shared_libraries", + enabled = True, + ) + + user_link_flags_feature = feature( + name = "user_link_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{user_link_flags}"], + iterate_over = "user_link_flags", + expand_if_available = "user_link_flags", + ), + ], + ), + ], + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = [ + "/DCOMPILER_MSVC", + "/DNOMINMAX", + "/D_WIN32_WINNT=0x0601", + "/D_CRT_SECURE_NO_DEPRECATE", + "/D_CRT_SECURE_NO_WARNINGS", + "/bigobj", + "/Zm500", + "/EHsc", + "/wd4351", + "/wd4291", + "/wd4250", + "/wd4996", + ], + ), + ], + ), + ], + ) + + msvc_compile_env_feature = feature( + name = "msvc_compile_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + env_entries = [env_entry(key = "INCLUDE", value = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE;C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um;C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt;")], + ), + ], + ) + + preprocessor_defines_feature = feature( + name = "preprocessor_defines", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/D%{preprocessor_defines}"], + iterate_over = "preprocessor_defines", + ), + ], + ), + ], + ) + + generate_pdb_file_feature = feature( + name = "generate_pdb_file", + requires = [ + feature_set(features = ["dbg"]), + feature_set(features = ["fastbuild"]), + ], + ) + + output_execpath_flags_feature = feature( + name = "output_execpath_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + dynamic_link_msvcrt_no_debug_feature = feature( + name = "dynamic_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MD"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + disable_assertions_feature = feature( + name = "disable_assertions", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/DNDEBUG"])], + with_features = [with_feature_set(features = ["opt"])], + ), + ], + ) + + has_configured_linker_path_feature = feature(name = "has_configured_linker_path") + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + no_stripping_feature = feature(name = "no_stripping") + + linker_param_file_feature = feature( + name = "linker_param_file", + flag_sets = [ + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["@%{linker_param_file}"], + expand_if_available = "linker_param_file", + ), + ], + ), + ], + ) + + ignore_noisy_warnings_feature = feature( + name = "ignore_noisy_warnings", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [flag_group(flags = ["/ignore:4221"])], + ), + ], + ) + + no_legacy_features_feature = feature(name = "no_legacy_features") + + parse_showincludes_feature = feature( + name = "parse_showincludes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ], + flag_groups = [flag_group(flags = ["/showIncludes"])], + ), + ], + ) + + static_link_msvcrt_no_debug_feature = feature( + name = "static_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MT"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + treat_warnings_as_errors_feature = feature( + name = "treat_warnings_as_errors", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/WX"])], + ), + ], + ) + + windows_export_all_symbols_feature = feature(name = "windows_export_all_symbols") + + no_windows_export_all_symbols_feature = feature(name = "no_windows_export_all_symbols") + + include_paths_feature = feature( + name = "include_paths", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/I%{quote_include_paths}"], + iterate_over = "quote_include_paths", + ), + flag_group( + flags = ["/I%{include_paths}"], + iterate_over = "include_paths", + ), + flag_group( + flags = ["/I%{system_include_paths}"], + iterate_over = "system_include_paths", + ), + ], + ), + ], + ) + + linkstamps_feature = feature( + name = "linkstamps", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{linkstamp_paths}"], + iterate_over = "linkstamp_paths", + expand_if_available = "linkstamp_paths", + ), + ], + ), + ], + ) + + targets_windows_feature = feature( + name = "targets_windows", + enabled = True, + implies = ["copy_dynamic_libraries_to_binary"], + ) + + linker_subsystem_flag_feature = feature( + name = "linker_subsystem_flag", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/SUBSYSTEM:CONSOLE"])], + ), + ], + ) + + static_link_msvcrt_debug_feature = feature( + name = "static_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MTd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + frame_pointer_feature = feature( + name = "frame_pointer", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Oy-"])], + ), + ], + ) + + compiler_output_flags_feature = feature( + name = "compiler_output_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.assemble], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}", "/Zi"], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + ], + expand_if_not_available = "output_preprocess_file", + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}"], + expand_if_not_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fa%{output_file}"], + expand_if_available = "output_assembly_file", + ), + ], + expand_if_available = "output_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/P", "/Fi%{output_file}"], + expand_if_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + ), + ], + ), + ], + ) + + nologo_feature = feature( + name = "nologo", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + flag_groups = [flag_group(flags = ["/nologo"])], + ), + ], + ) + + smaller_binary_feature = feature( + name = "smaller_binary", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Gy", "/Gw"])], + with_features = [with_feature_set(features = ["opt"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/OPT:ICF", "/OPT:REF"])], + with_features = [with_feature_set(features = ["opt"])], + ), + ], + ) + + compiler_input_flags_feature = feature( + name = "compiler_input_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["/c", "%{source_file}"], + expand_if_available = "source_file", + ), + ], + ), + ], + ) + + def_file_feature = feature( + name = "def_file", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEF:%{def_file_path}", "/ignore:4070"], + expand_if_available = "def_file_path", + ), + ], + ), + ], + ) + + msvc_env_feature = feature( + name = "msvc_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\amd64;C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319;C:\\Windows\\Microsoft.NET\\Framework64\\;C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x64;C:\\Program Files (x86)\\Windows Kits\\8.1\\bin\\x86;;C:\\Windows\\system32"), + env_entry(key = "TMP", value = "C:\\Users\\ContainerAdministrator\\AppData\\Local\\Temp"), + env_entry(key = "TEMP", value = "C:\\Users\\ContainerAdministrator\\AppData\\Local\\Temp"), + ], + ), + ], + implies = ["msvc_compile_env", "msvc_link_env"], + ) + + features = [ + no_legacy_features_feature, + nologo_feature, + has_configured_linker_path_feature, + no_stripping_feature, + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + default_compile_flags_feature, + msvc_env_feature, + msvc_compile_env_feature, + msvc_link_env_feature, + include_paths_feature, + preprocessor_defines_feature, + parse_showincludes_feature, + generate_pdb_file_feature, + shared_flag_feature, + linkstamps_feature, + output_execpath_flags_feature, + archiver_flags_feature, + input_param_flags_feature, + linker_subsystem_flag_feature, + user_link_flags_feature, + default_link_flags_feature, + linker_param_file_feature, + static_link_msvcrt_feature, + static_link_msvcrt_no_debug_feature, + dynamic_link_msvcrt_no_debug_feature, + static_link_msvcrt_debug_feature, + dynamic_link_msvcrt_debug_feature, + dbg_feature, + fastbuild_feature, + opt_feature, + frame_pointer_feature, + disable_assertions_feature, + determinism_feature, + treat_warnings_as_errors_feature, + smaller_binary_feature, + ignore_noisy_warnings_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + compiler_output_flags_feature, + compiler_input_flags_feature, + def_file_feature, + windows_export_all_symbols_feature, + no_windows_export_all_symbols_feature, + supports_dynamic_linker_feature, + supports_interface_shared_libraries_feature, + ] + + artifact_name_patterns = [ + artifact_name_pattern( + category_name = "object_file", + prefix = "", + extension = ".obj", + ), + artifact_name_pattern( + category_name = "static_library", + prefix = "", + extension = ".lib", + ), + artifact_name_pattern( + category_name = "alwayslink_static_library", + prefix = "", + extension = ".lo.lib", + ), + artifact_name_pattern( + category_name = "executable", + prefix = "", + extension = ".exe", + ), + artifact_name_pattern( + category_name = "dynamic_library", + prefix = "", + extension = ".dll", + ), + artifact_name_pattern( + category_name = "interface_library", + prefix = "", + extension = ".if.lib", + ), + ] + + make_variables = [] + + tool_paths = [ + tool_path(name = "ar", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/lib.exe"), + tool_path(name = "ml", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/ml64.exe"), + tool_path(name = "cpp", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe"), + tool_path(name = "gcc", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe"), + tool_path(name = "gcov", path = "wrapper/bin/msvc_nop.bat"), + tool_path(name = "ld", path = "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/link.exe"), + tool_path(name = "nm", path = "wrapper/bin/msvc_nop.bat"), + tool_path( + name = "objcopy", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "objdump", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "strip", + path = "wrapper/bin/msvc_nop.bat", + ), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = builtin_sysroot, + cc_target_os = None, + ) + +def _windows_msys_mingw_impl(ctx): + toolchain_identifier = "msys_x64_mingw" + host_system_name = "local" + target_system_name = "local" + target_cpu = "x64_windows" + target_libc = "mingw" + compiler = "mingw-gcc" + abi_version = "local" + abi_libc_version = "local" + cc_target_os = None + builtin_sysroot = None + action_configs = [] + + targets_windows_feature = feature( + name = "targets_windows", + implies = ["copy_dynamic_libraries_to_binary"], + enabled = True, + ) + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + gcc_env_feature = feature( + name = "gcc_env", + enabled = True, + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = "c:/tools/msys64/mingw64/bin"), + ], + ), + ], + ) + + msys_mingw_flags = [ + "-std=gnu++0x", + ] + msys_mingw_link_flags = [ + "-lstdc++", + ] + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + ), + flag_set( + actions = [ + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = msys_mingw_flags)] if msys_mingw_flags else []), + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = ([flag_group(flags = msys_mingw_link_flags)] if msys_mingw_link_flags else []), + ), + ], + ) + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + features = [ + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + gcc_env_feature, + default_compile_flags_feature, + default_link_flags_feature, + supports_dynamic_linker_feature, + ] + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + "c:/tools/msys64/mingw64/", + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE", + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt", + ] + + artifact_name_patterns = [ + artifact_name_pattern( + category_name = "executable", + prefix = "", + extension = ".exe", + ), + ] + + make_variables = [] + tool_paths = [ + tool_path(name = "ar", path = "c:/tools/msys64/mingw64/bin/ar"), + tool_path(name = "compat-ld", path = "c:/tools/msys64/mingw64/bin/ld"), + tool_path(name = "cpp", path = "c:/tools/msys64/mingw64/bin/cpp"), + tool_path(name = "dwp", path = "c:/tools/msys64/mingw64/bin/dwp"), + tool_path(name = "gcc", path = "c:/tools/msys64/mingw64/bin/gcc"), + tool_path(name = "gcov", path = "c:/tools/msys64/mingw64/bin/gcov"), + tool_path(name = "ld", path = "c:/tools/msys64/mingw64/bin/ld"), + tool_path(name = "nm", path = "c:/tools/msys64/mingw64/bin/nm"), + tool_path(name = "objcopy", path = "c:/tools/msys64/mingw64/bin/objcopy"), + tool_path(name = "objdump", path = "c:/tools/msys64/mingw64/bin/objdump"), + tool_path(name = "strip", path = "c:/tools/msys64/mingw64/bin/strip"), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = builtin_sysroot, + cc_target_os = cc_target_os, + ) + +def _armeabi_impl(ctx): + toolchain_identifier = "stub_armeabi-v7a" + host_system_name = "armeabi-v7a" + target_system_name = "armeabi-v7a" + target_cpu = "armeabi-v7a" + target_libc = "armeabi-v7a" + compiler = "compiler" + abi_version = "armeabi-v7a" + abi_libc_version = "armeabi-v7a" + cc_target_os = None + builtin_sysroot = None + action_configs = [] + + supports_pic_feature = feature(name = "supports_pic", enabled = True) + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + features = [supports_dynamic_linker_feature, supports_pic_feature] + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + ] + artifact_name_patterns = [] + make_variables = [] + + tool_paths = [ + tool_path(name = "ar", path = "/bin/false"), + tool_path(name = "compat-ld", path = "/bin/false"), + tool_path(name = "cpp", path = "/bin/false"), + tool_path(name = "dwp", path = "/bin/false"), + tool_path(name = "gcc", path = "/bin/false"), + tool_path(name = "gcov", path = "/bin/false"), + tool_path(name = "ld", path = "/bin/false"), + tool_path(name = "nm", path = "/bin/false"), + tool_path(name = "objcopy", path = "/bin/false"), + tool_path(name = "objdump", path = "/bin/false"), + tool_path(name = "strip", path = "/bin/false"), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = builtin_sysroot, + cc_target_os = cc_target_os, + ) + +def _impl(ctx): + if ctx.attr.cpu == "armeabi-v7a": + return _armeabi_impl(ctx) + elif ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "msvc-cl": + return _windows_msvc_impl(ctx) + elif ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "mingw-gcc": + return _windows_msys_mingw_impl(ctx) + + tool_paths = [ + tool_path(name = "ar", path = "c:/tools/msys64/usr/bin/ar"), + tool_path(name = "compat-ld", path = "c:/tools/msys64/usr/bin/ld"), + tool_path(name = "cpp", path = "c:/tools/msys64/usr/bin/cpp"), + tool_path(name = "dwp", path = "c:/tools/msys64/usr/bin/dwp"), + tool_path(name = "gcc", path = "c:/tools/msys64/usr/bin/gcc"), + tool_path(name = "gcov", path = "c:/tools/msys64/usr/bin/gcov"), + tool_path(name = "ld", path = "c:/tools/msys64/usr/bin/ld"), + tool_path(name = "nm", path = "c:/tools/msys64/usr/bin/nm"), + tool_path(name = "objcopy", path = "c:/tools/msys64/usr/bin/objcopy"), + tool_path(name = "objdump", path = "c:/tools/msys64/usr/bin/objdump"), + tool_path(name = "strip", path = "c:/tools/msys64/usr/bin/strip"), + ] + + cxx_builtin_include_directories = [ + # This is a workaround for https://github.com/bazelbuild/bazel/issues/5087. + "C:\\botcode\\w", + "c:/tools/msys64/usr/", + "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\INCLUDE", + "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.10240.0\\ucrt", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", + "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt", + ] + + action_configs = [] + + compile_flags = [ + ] + + dbg_compile_flags = [ + ] + + opt_compile_flags = [ + ] + + cxx_flags = [ + "-std=gnu++0x", + ] + + link_flags = [ + "-lstdc++", + ] + + opt_link_flags = [ + ] + + unfiltered_compile_flags = [ + ] + + targets_windows_feature = feature( + name = "targets_windows", + implies = ["copy_dynamic_libraries_to_binary"], + enabled = True, + ) + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + gcc_env_feature = feature( + name = "gcc_env", + enabled = True, + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = "c:/tools/msys64/usr/bin"), + ], + ), + ], + ) + + windows_features = [ + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + gcc_env_feature, + ] + + supports_pic_feature = feature( + name = "supports_pic", + enabled = True, + ) + supports_start_end_lib_feature = feature( + name = "supports_start_end_lib", + enabled = True, + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = compile_flags)] if compile_flags else []), + ), + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = dbg_compile_flags)] if dbg_compile_flags else []), + with_features = [with_feature_set(features = ["dbg"])], + ), + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = opt_compile_flags)] if opt_compile_flags else []), + with_features = [with_feature_set(features = ["opt"])], + ), + flag_set( + actions = [ + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = cxx_flags)] if cxx_flags else []), + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = ([flag_group(flags = link_flags)] if link_flags else []), + ), + flag_set( + actions = all_link_actions, + flag_groups = ([flag_group(flags = opt_link_flags)] if opt_link_flags else []), + with_features = [with_feature_set(features = ["opt"])], + ), + ], + ) + + dbg_feature = feature(name = "dbg") + + opt_feature = feature(name = "opt") + + sysroot_feature = feature( + name = "sysroot", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + fdo_optimize_feature = feature( + name = "fdo_optimize", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-fprofile-use=%{fdo_profile_path}", + "-fprofile-correction", + ], + expand_if_available = "fdo_profile_path", + ), + ], + ), + ], + provides = ["profile"], + ) + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + user_compile_flags_feature = feature( + name = "user_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = ([flag_group(flags = unfiltered_compile_flags)] if unfiltered_compile_flags else []), + ), + ], + ) + + features = windows_features + [ + supports_pic_feature, + default_compile_flags_feature, + default_link_flags_feature, + fdo_optimize_feature, + supports_dynamic_linker_feature, + dbg_feature, + opt_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + ] + + artifact_name_patterns = [ + artifact_name_pattern(category_name = "executable", prefix = "", extension = ".exe"), + ] + + make_variables = [] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = "msys_x64", + host_system_name = "local", + target_system_name = "local", + target_cpu = "x64_windows", + target_libc = "msys", + compiler = "msys-gcc", + abi_version = "local", + abi_libc_version = "local", + tool_paths = tool_paths, + make_variables = make_variables, + builtin_sysroot = "", + cc_target_os = None, + ) + +cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "cpu": attr.string(mandatory = True), + "compiler": attr.string(), + }, + provides = [CcToolchainConfigInfo], +) diff --git a/third_party/toolchains/bazel_0.23.2_rbe_windows/dummy_toolchain.bzl b/third_party/toolchains/bazel_0.23.2_rbe_windows/dummy_toolchain.bzl new file mode 100644 index 00000000000..45c0285d232 --- /dev/null +++ b/third_party/toolchains/bazel_0.23.2_rbe_windows/dummy_toolchain.bzl @@ -0,0 +1,23 @@ +# pylint: disable=g-bad-file-header +# Copyright 2017 The Bazel Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Skylark rule that stubs a toolchain.""" + +def _dummy_toolchain_impl(ctx): + ctx = ctx # unused argument + toolchain = platform_common.ToolchainInfo() + return [toolchain] + +dummy_toolchain = rule(_dummy_toolchain_impl, attrs = {}) diff --git a/tools/codegen/core/gen_upb_api.sh b/tools/codegen/core/gen_upb_api.sh index 2ca36b70661..ff21c49362c 100755 --- a/tools/codegen/core/gen_upb_api.sh +++ b/tools/codegen/core/gen_upb_api.sh @@ -52,7 +52,9 @@ proto_files=( \ "envoy/api/v2/cds.proto" \ "envoy/api/v2/eds.proto" \ "envoy/api/v2/endpoint/endpoint.proto" \ - "envoy/service/discovery/v2/ads.proto") + "envoy/api/v2/endpoint/load_report.proto" \ + "envoy/service/discovery/v2/ads.proto" \ + "envoy/service/load_stats/v2/lrs.proto") for i in "${proto_files[@]}" do diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py index 950b2e2d111..22d04c5a1af 100644 --- a/tools/distrib/python/grpcio_tools/grpc_version.py +++ b/tools/distrib/python/grpcio_tools/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!! -VERSION = '1.20.0.dev0' +VERSION = '1.21.0.dev0' diff --git a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile index 894f114951c..aeedec8153f 100644 --- a/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile +++ b/tools/dockerfile/distribtest/cpp_jessie_x64/Dockerfile @@ -13,6 +13,7 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list # Install packages needed for gRPC and protobuf RUN apt-get update && apt-get install -y \ @@ -29,7 +30,9 @@ RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y golang && apt-get clean -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean CMD ["bash"] diff --git a/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile index e32b3cb5e25..d9473bb3a5c 100644 --- a/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile +++ b/tools/dockerfile/distribtest/csharp_centos7_x64/Dockerfile @@ -18,6 +18,7 @@ RUN rpm --import "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0 RUN curl https://download.mono-project.com/repo/centos7-stable.repo | tee /etc/yum.repos.d/mono-centos7-stable.repo RUN yum install -y mono-devel +RUN yum install -y msbuild RUN yum install -y nuget diff --git a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile index f247cc9ca54..a0fef12d6e1 100644 --- a/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x64/Dockerfile @@ -15,6 +15,7 @@ # Docker file for building gRPC artifacts. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -49,7 +50,8 @@ RUN apt-get update && apt-get install -y \ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN apt-get update && apt-get install -y gnupg2 +RUN gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.1 @@ -72,7 +74,9 @@ RUN apt-get update && apt-get install -y \ # C# dependencies (needed to build grpc_csharp_ext) # Use cmake 3.6 from jessie-backports -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile index e403f75b594..8709fe0426c 100644 --- a/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile +++ b/tools/dockerfile/grpc_artifact_linux_x86/Dockerfile @@ -15,6 +15,7 @@ # Docker file for building gRPC artifacts. FROM 32bit/debian:jessie +RUN sed -i '/deb http:\/\/http.debian.net\/debian jessie-updates main/d' /etc/apt/sources.list # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -49,7 +50,9 @@ RUN apt-get update && apt-get install -y \ # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +# Install rvm +RUN apt-get update && apt-get install -y gnupg2 +RUN gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.1 @@ -64,7 +67,9 @@ RUN /bin/bash -l -c "gem install bundler -v 1.17.3 --no-ri --no-rdoc" # C# dependencies (needed to build grpc_csharp_ext) # Use cmake 3.6 from jessie-backports -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/grpc_clang_format/Dockerfile b/tools/dockerfile/grpc_clang_format/Dockerfile index ecdc52ee316..8e5edf75d52 100644 --- a/tools/dockerfile/grpc_clang_format/Dockerfile +++ b/tools/dockerfile/grpc_clang_format/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + RUN apt-get update && apt-get -y install wget xz-utils RUN wget http://releases.llvm.org/5.0.0/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04.tar.xz diff --git a/tools/dockerfile/grpc_clang_tidy/Dockerfile b/tools/dockerfile/grpc_clang_tidy/Dockerfile index dec7680fcf7..2e0e683c202 100644 --- a/tools/dockerfile/grpc_clang_tidy/Dockerfile +++ b/tools/dockerfile/grpc_clang_tidy/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + RUN apt-get update && apt-get -y install wget xz-utils RUN wget http://releases.llvm.org/5.0.0/clang+llvm-5.0.0-linux-x86_64-ubuntu14.04.tar.xz diff --git a/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh index ce21e0f335d..2a3e6f3a0ee 100644 --- a/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_aspnetcore/build_interop.sh @@ -26,9 +26,15 @@ cd /var/local/git/grpc-dotnet # If needed, update dotnet SDK and put it on path ./build/get-dotnet.sh -if [ -f $HOME/.dotnet/dotnet ] +# Normally we would source ./activate.sh +# to add dotnet to PATH, but that would only +# work for the build and not for a subsequent +# dotnet run from a different shell, +# so we create a symlink instead. +# TODO(jtattermusch): Come up with a cleaner solution. +if [ -f $(pwd)/.dotnet/dotnet ] then - ln -s $HOME/.dotnet/dotnet /usr/local/bin/dotnet + ln -s $(pwd)/.dotnet/dotnet /usr/local/bin/dotnet fi ./build/get-grpc.sh diff --git a/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile index 9ede89b78d4..1fe64a462aa 100644 --- a/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile index fc29ada0d2d..217175159df 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile @@ -13,46 +13,23 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list -# Install JDK 8 and Git + +# Install JDK 8 # 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/ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && \ + apt-get update && apt-get -y install 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 -#==================== -# 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 --upgrade pip==10.0.1 -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0 - - -# Trigger download of as many Gradle artifacts as possible. -RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && \ - cd grpc-java && \ - ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true && \ - rm -r "$(pwd)" # Define the default command. CMD ["bash"] + diff --git a/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh index 0e36c193c91..8e1154679d7 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_java/build_interop.sh @@ -16,16 +16,24 @@ # Builds Java interop server and client in a base image. set -e -mkdir -p /var/local/git -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java +cp -r /var/local/jenkins/grpc-java /tmp/grpc-java # copy service account keys if available cp -r /var/local/jenkins/service_account $HOME || true -cd /var/local/git/grpc-java - +pushd /tmp/grpc-java ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true +mkdir -p /var/local/git/grpc-java/ +cp -r --parents -t /var/local/git/grpc-java/ \ + interop-testing/build/install/ \ + run-test-client.sh \ + run-test-server.sh + +popd +rm -r /tmp/grpc-java +rm -r "$HOME/.gradle" + # enable extra java logging mkdir -p /var/local/grpc_java_logging echo "handlers = java.util.logging.ConsoleHandler diff --git a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile index fc29ada0d2d..217175159df 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile @@ -13,46 +13,23 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list -# Install JDK 8 and Git + +# Install JDK 8 # 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/ + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 && \ + apt-get update && apt-get -y install 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 -#==================== -# 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 --upgrade pip==10.0.1 -RUN pip install virtualenv -RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0 - - -# Trigger download of as many Gradle artifacts as possible. -RUN git clone --recursive --depth 1 https://github.com/grpc/grpc-java.git && \ - cd grpc-java && \ - ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true && \ - rm -r "$(pwd)" # Define the default command. CMD ["bash"] + diff --git a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh index 4c5ba4b7a3a..77d322882f7 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh +++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/build_interop.sh @@ -16,16 +16,24 @@ # Builds Java interop server and client in a base image. set -e -mkdir -p /var/local/git -git clone --recursive --depth 1 /var/local/jenkins/grpc-java /var/local/git/grpc-java +cp -r /var/local/jenkins/grpc-java /tmp/grpc-java # copy service account keys if available cp -r /var/local/jenkins/service_account $HOME || true -cd /var/local/git/grpc-java - +pushd /tmp/grpc-java ./gradlew :grpc-interop-testing:installDist -PskipCodegen=true +mkdir -p /var/local/git/grpc-java/ +cp -r --parents -t /var/local/git/grpc-java/ \ + interop-testing/build/install/ \ + run-test-client.sh \ + run-test-server.sh + +popd +rm -r /tmp/grpc-java +rm -r "$HOME/.gradle" + # enable extra java logging mkdir -p /var/local/grpc_java_logging echo "handlers = java.util.logging.ConsoleHandler diff --git a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile index 015641684b0..96adf6edd86 100644 --- a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile index 0006be790ee..88e3cfacd97 100644 --- a/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_nodepurejs/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile index e987d4c88eb..c9c141e5d54 100644 --- a/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_php/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile index 71a2381b776..84241391dfc 100644 --- a/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_php7/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + #================= # PHP7 dependencies diff --git a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile index 1f6f03edd89..cce5e86cd37 100644 --- a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -68,7 +70,8 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN apt-get update && apt-get install -y gnupg2 +RUN gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.5 @@ -77,7 +80,7 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.5" RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.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.5' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-document" +RUN /bin/bash -l -c "gem install bundler --no-document -v 1.9" RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/bazel/Dockerfile b/tools/dockerfile/test/bazel/Dockerfile index 7dee0051176..2536fe299cb 100644 --- a/tools/dockerfile/test/bazel/Dockerfile +++ b/tools/dockerfile/test/bazel/Dockerfile @@ -52,9 +52,9 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ - bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ - rm bazel-0.20.0-installer-linux-x86_64.sh +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-installer-linux-x86_64.sh && \ + bash ./bazel-0.23.2-installer-linux-x86_64.sh && \ + rm bazel-0.23.2-installer-linux-x86_64.sh RUN mkdir -p /var/local/jenkins diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile index f9dc8f20d7c..c46f9618b17 100644 --- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -76,7 +78,9 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile index 76015c8c42d..59b86d7247c 100644 --- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile +++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile @@ -13,6 +13,7 @@ # limitations under the License. FROM 32bit/debian:jessie +RUN sed -i '/deb http:\/\/http.debian.net\/debian jessie-updates main/d' /etc/apt/sources.list # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -79,7 +80,9 @@ RUN mkdir /var/local/jenkins # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean diff --git a/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile index 77aac3cdec7..8bf122cd5b2 100644 --- a/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/cxx_sanitizers_jessie_x64/Dockerfile @@ -14,6 +14,7 @@ # This is the base Docker image we use for running tests on RBE FROM gcr.io/cloud-marketplace/google/rbe-debian8@sha256:1ede2a929b44d629ec5abe86eee6d7ffea1d5a4d247489a8867d46cfde3e38bd +RUN sed -i '/deb http:\/\/httpredir.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile index 7f871f2f62a..14e447891da 100644 --- a/tools/dockerfile/test/fuzzer/Dockerfile +++ b/tools/dockerfile/test/fuzzer/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -76,7 +78,9 @@ RUN apt-get update && apt-get -y install libgflags-dev libgtest-dev libc++-dev c # Use cmake 3.6 from jessie-backports # should only be used for images based on debian jessie. -RUN echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo "deb http://archive.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list +RUN echo 'Acquire::Check-Valid-Until "false";' > /etc/apt/apt.conf +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list RUN apt-get update && apt-get install -t jessie-backports -y cmake && apt-get clean #================= diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile index 7c36fb37345..0ef32109ded 100644 --- a/tools/dockerfile/test/node_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. 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 fac9eb55517..a32b764cfb9 100644 --- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + #================= # PHP7 dependencies diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile index ed59e569956..ebbbcf524cd 100644 --- a/tools/dockerfile/test/php_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/test/python_jessie_x64/Dockerfile b/tools/dockerfile/test/python_jessie_x64/Dockerfile index a4c3a9f91e1..5ac3af8b26d 100644 --- a/tools/dockerfile/test/python_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/python_jessie_x64/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ diff --git a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile index cf6a5b254f1..ae460756f88 100644 --- a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile +++ b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile @@ -13,6 +13,8 @@ # limitations under the License. FROM debian:jessie +RUN sed -i '/deb http:\/\/deb.debian.org\/debian jessie-updates main/d' /etc/apt/sources.list + # Install Git and basic packages. RUN apt-get update && apt-get install -y \ @@ -72,7 +74,8 @@ RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 t # Ruby dependencies # Install rvm -RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB +RUN apt-get update && apt-get install -y gnupg2 +RUN gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB RUN \curl -sSL https://get.rvm.io | bash -s stable # Install Ruby 2.5 @@ -81,7 +84,7 @@ RUN /bin/bash -l -c "rvm use --default ruby-2.5" RUN /bin/bash -l -c "echo 'gem: --no-document' > ~/.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.5' >> ~/.bashrc" -RUN /bin/bash -l -c "gem install bundler --no-document" +RUN /bin/bash -l -c "gem install bundler --no-document -v 1.9" RUN mkdir /var/local/jenkins diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile index 7a6fbfee7f4..765bd7267a4 100644 --- a/tools/dockerfile/test/sanity/Dockerfile +++ b/tools/dockerfile/test/sanity/Dockerfile @@ -98,9 +98,9 @@ ENV CLANG_TIDY=clang-tidy # Bazel installation RUN apt-get update && apt-get install -y wget && apt-get clean -RUN wget https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-installer-linux-x86_64.sh && \ - bash ./bazel-0.20.0-installer-linux-x86_64.sh && \ - rm bazel-0.20.0-installer-linux-x86_64.sh +RUN wget https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-installer-linux-x86_64.sh && \ + bash ./bazel-0.23.2-installer-linux-x86_64.sh && \ + rm bazel-0.23.2-installer-linux-x86_64.sh # Define the default command. diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 9f17a25298a..7274f9588b3 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.20.0-dev +PROJECT_NUMBER = 1.21.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -930,12 +930,16 @@ include/grpcpp/channel.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ +include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ +include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ +include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ +include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -991,18 +995,25 @@ include/grpcpp/impl/rpc_method.h \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ +include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ +include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ +include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ +include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ +include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 1e17ab8f88b..f169199ae96 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.20.0-dev +PROJECT_NUMBER = 1.21.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -931,12 +931,16 @@ include/grpcpp/channel.h \ include/grpcpp/client_context.h \ include/grpcpp/completion_queue.h \ include/grpcpp/create_channel.h \ +include/grpcpp/create_channel_impl.h \ include/grpcpp/create_channel_posix.h \ +include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ +include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ +include/grpcpp/health_check_service_interface_impl.h \ include/grpcpp/impl/call.h \ include/grpcpp/impl/channel_argument_option.h \ include/grpcpp/impl/client_unary_call.h \ @@ -993,18 +997,25 @@ include/grpcpp/impl/rpc_method.h \ include/grpcpp/impl/rpc_service_method.h \ include/grpcpp/impl/serialization_traits.h \ include/grpcpp/impl/server_builder_option.h \ +include/grpcpp/impl/server_builder_option_impl.h \ include/grpcpp/impl/server_builder_plugin.h \ include/grpcpp/impl/server_initializer.h \ +include/grpcpp/impl/server_initializer_impl.h \ include/grpcpp/impl/service_type.h \ include/grpcpp/resource_quota.h \ +include/grpcpp/resource_quota_impl.h \ include/grpcpp/security/auth_context.h \ include/grpcpp/security/auth_metadata_processor.h \ +include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ +include/grpcpp/server_builder_impl.h \ include/grpcpp/server_context.h \ include/grpcpp/server_posix.h \ +include/grpcpp/server_posix_impl.h \ include/grpcpp/support/async_stream.h \ include/grpcpp/support/async_unary_call.h \ include/grpcpp/support/byte_buffer.h \ @@ -1072,10 +1083,12 @@ src/core/lib/gprpp/debug_location.h \ src/core/lib/gprpp/fork.h \ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ +src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ +src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ src/core/lib/gprpp/thd.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 0fdab21483c..e68e758c64e 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1164,10 +1164,12 @@ src/core/lib/gprpp/fork.cc \ src/core/lib/gprpp/fork.h \ src/core/lib/gprpp/inlined_vector.h \ src/core/lib/gprpp/manual_constructor.h \ +src/core/lib/gprpp/map.h \ src/core/lib/gprpp/memory.h \ src/core/lib/gprpp/mutex_lock.h \ src/core/lib/gprpp/optional.h \ src/core/lib/gprpp/orphanable.h \ +src/core/lib/gprpp/pair.h \ src/core/lib/gprpp/ref_counted.h \ src/core/lib/gprpp/ref_counted_ptr.h \ src/core/lib/gprpp/thd.h \ diff --git a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh index 903166122eb..1b014ad4a8e 100755 --- a/tools/gce/create_linux_kokoro_performance_worker_from_image.sh +++ b/tools/gce/create_linux_kokoro_performance_worker_from_image.sh @@ -22,7 +22,7 @@ cd "$(dirname "$0")" CLOUD_PROJECT=grpc-testing ZONE=us-central1-b # this zone allows 32core machines -LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v4 # update if newer image exists +LATEST_PERF_WORKER_IMAGE=grpc-performance-kokoro-v5 # update if newer image exists INSTANCE_NAME="${1:-grpc-kokoro-performance-server}" MACHINE_TYPE="${2:-n1-standard-32}" diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh index 1bf2228279e..46061a0cc67 100755 --- a/tools/gce/linux_kokoro_performance_worker_init.sh +++ b/tools/gce/linux_kokoro_performance_worker_init.sh @@ -219,6 +219,8 @@ touch /tmpfs/READY # See https://github.com/grpc/grpc/issues/17794 sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/10periodic sudo sed -i 's/APT::Periodic::AutocleanInterval "1"/APT::Periodic::AutocleanInterval "0"/' /etc/apt/apt.conf.d/10periodic +sudo sed -i 's/APT::Periodic::Update-Package-Lists "1"/APT::Periodic::Update-Package-Lists "0"/' /etc/apt/apt.conf.d/20auto-upgrades +sudo sed -i 's/APT::Periodic::Unattended-Upgrade "1"/APT::Periodic::Unattended-Upgrade "0"/' /etc/apt/apt.conf.d/20auto-upgrades # Restart for VM to pick up kernel update echo 'Successfully initialized the linux worker, going for reboot in 10 seconds' diff --git a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh index 24598f43f02..3dd0167b7c0 100755 --- a/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_bazel_build_in_docker.sh @@ -24,4 +24,5 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc && git submodule update --init --reference /var/local/jenkins/grpc/${name} \ ${name}') cd /var/local/git/grpc -bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... examples/... +#TODO(yfen): add back examples/... to build targets once python rules issues are resolved +bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh index 863b43a1728..dd34eac7b38 100755 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh @@ -23,7 +23,7 @@ cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321 # Download bazel temp_dir="$(mktemp -d)" -wget -q https://github.com/bazelbuild/bazel/releases/download/0.20.0/bazel-0.20.0-linux-x86_64 -O "${temp_dir}/bazel" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-linux-x86_64 -O "${temp_dir}/bazel" chmod 755 "${temp_dir}/bazel" export PATH="${temp_dir}:${PATH}" # This should show ${temp_dir}/bazel diff --git a/tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh b/tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh new file mode 100644 index 00000000000..9c3712a07da --- /dev/null +++ b/tools/internal_ci/linux/grpc_bazel_rbe_incompatible_changes.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -ex + +# TODO(jtattermusch): use the latest version of bazel + +# Use --all_incompatible_changes to give an early warning about future +# bazel incompatibilities. +EXTRA_FLAGS="--config=opt --cache_test_results=no --all_incompatible_changes" +github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}" diff --git a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh index d844cff7f9a..3ca4673ca08 100755 --- a/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh +++ b/tools/internal_ci/linux/grpc_python_bazel_test_in_docker.sh @@ -23,9 +23,10 @@ git clone /var/local/jenkins/grpc /var/local/git/grpc (cd /var/local/jenkins/grpc/ && git submodule foreach 'cd /var/local/git/grpc \ && git submodule update --init --reference /var/local/jenkins/grpc/${name} \ ${name}') -cd /var/local/git/grpc/test -bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... -bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... -bazel clean --expunge -bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... -bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... +#TODO(yfen): temporarily disabled all python bazel tests due to incompatibility with bazel 0.23.2 +#cd /var/local/git/grpc/test +#bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... +#bazel test --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... +#bazel clean --expunge +#bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //src/python/... +#bazel test --config=python3 --spawn_strategy=standalone --genrule_strategy=standalone --test_output=errors //examples/python/... diff --git a/tools/internal_ci/macos/grpc_run_bazel_tests.sh b/tools/internal_ci/macos/grpc_run_bazel_tests.sh index ef02a675d5b..56fae8fd75f 100644 --- a/tools/internal_ci/macos/grpc_run_bazel_tests.sh +++ b/tools/internal_ci/macos/grpc_run_bazel_tests.sh @@ -18,6 +18,13 @@ set -ex # change to grpc repo root cd $(dirname $0)/../../.. +# Download bazel +temp_dir="$(mktemp -d)" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-darwin-x86_64 -O "${temp_dir}/bazel" +chmod 755 "${temp_dir}/bazel" +export PATH="${temp_dir}:${PATH}" +# This should show ${temp_dir}/bazel +which bazel ./tools/run_tests/start_port_server.py diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py index 654dfd6faef..013b9d0f1ee 100644 --- a/tools/interop_matrix/client_matrix.py +++ b/tools/interop_matrix/client_matrix.py @@ -99,6 +99,7 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo()), ('v1.17.1', ReleaseInfo()), ('v1.18.0', ReleaseInfo()), + ('v1.19.0', ReleaseInfo()), ]), 'go': OrderedDict([ @@ -164,6 +165,7 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo(testcases_file='python__v1.11.1')), ('v1.17.1', ReleaseInfo(testcases_file='python__v1.11.1')), ('v1.18.0', ReleaseInfo()), + ('v1.19.0', ReleaseInfo()), ]), 'node': OrderedDict([ @@ -210,6 +212,9 @@ LANG_RELEASE_MATRIX = { ReleaseInfo(patch=[ 'tools/dockerfile/interoptest/grpc_interop_ruby/build_interop.sh', ])), + # TODO: https://github.com/grpc/grpc/issues/18262. + # If you are not encountering the error in above issue + # go ahead and upload the docker image for new releases. ]), 'php': OrderedDict([ @@ -231,6 +236,8 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo()), ('v1.17.1', ReleaseInfo()), ('v1.18.0', ReleaseInfo()), + # TODO:https://github.com/grpc/grpc/issues/18264 + # Error in above issues needs to be resolved. ]), 'csharp': OrderedDict([ @@ -258,5 +265,6 @@ LANG_RELEASE_MATRIX = { ('v1.16.0', ReleaseInfo(testcases_file='csharp__v1.3.9')), ('v1.17.1', ReleaseInfo(testcases_file='csharp__v1.3.9')), ('v1.18.0', ReleaseInfo()), + ('v1.19.0', ReleaseInfo()), ]), } diff --git a/tools/release/release_notes.py b/tools/release/release_notes.py new file mode 100644 index 00000000000..46e01843535 --- /dev/null +++ b/tools/release/release_notes.py @@ -0,0 +1,369 @@ +#Copyright 2019 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Generate draft and release notes in Markdown from Github PRs. + +You'll need a github API token to avoid being rate-limited. See +https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ + +This script collects PRs using "git log X..Y" from local repo where X and Y are +tags or release branch names of previous and current releases respectively. +Typically, notes are generated before the release branch is labelled so Y is +almost always the name of the release branch. X is the previous release branch +if this is not a patch release. Otherwise, it is the previous release tag. +For example, for release v1.17.0, X will be origin/v1.16.x and for release v1.17.3, +X will be v1.17.2. In both cases Y will be origin/v1.17.x. + +""" + +from collections import defaultdict +import base64 +import json + +content_header = """Draft Release Notes For {version} +-- +Final release notes will be generated from the PR titles that have *"release notes:yes"* label. If you have any additional notes please add them below. These will be appended to auto generated release notes. Previous releases notes are [here](https://github.com/grpc/grpc/releases). + +**Also, look at the PRs listed below against your name.** Please apply the missing labels and make necessary corrections (like fixing the title) to the PR in Github. Final release notes will be generated just before the release on {date}. + +Add additional notes not in PRs +-- + +Core +- + + +C++ +- + + +C# +- + + +Objective-C +- + + +PHP +- + + +Python +- + + +Ruby +- + + +""" + +rl_header = """This is the {version} release ([{name}](https://github.com/grpc/grpc/blob/master/doc/g_stands_for.md)) of gRPC Core. + +Please see the notes for the previous releases here: https://github.com/grpc/grpc/releases. Please consult https://grpc.io/ for all information regarding this product. + +This release contains refinements, improvements, and bug fixes, with highlights listed below. + + +""" + +HTML_URL = "https://github.com/grpc/grpc/pull/" +API_URL = 'https://api.github.com/repos/grpc/grpc/pulls/' + + +def get_commit_log(prevRelLabel, relBranch): + """Return the output of 'git log --pretty=online --merges prevRelLabel..relBranch' """ + + import subprocess + print("Running git log --pretty=oneline --merges " + prevRelLabel + ".." + + relBranch) + return subprocess.check_output([ + "git", "log", "--pretty=oneline", "--merges", + "%s..%s" % (prevRelLabel, relBranch) + ]) + + +def get_pr_data(pr_num): + """Get the PR data from github. Return 'error' on exception""" + + try: + from urllib2 import Request, urlopen, HTTPError + except ImportError: + import urllib + from urllib.request import Request, urlopen, HTTPError + url = API_URL + pr_num + req = Request(url) + req.add_header('Authorization', 'token %s' % TOKEN) + try: + f = urlopen(req) + response = json.loads(f.read().decode('utf-8')) + #print(response) + except HTTPError as e: + response = json.loads(e.fp.read().decode('utf-8')) + if 'message' in response: + print(response['message']) + response = "error" + return response + + +def get_pr_titles(gitLogs): + import re + error_count = 0 + match = b"Merge pull request #(\d+)" + prlist = re.findall(match, gitLogs, re.MULTILINE) + print("\nPRs matching 'Merge pull request #':") + print(prlist) + print("\n") + langs_pr = defaultdict(list) + for pr_num in prlist: + pr_num = str(pr_num) + print("---------- getting data for PR " + pr_num) + pr = get_pr_data(pr_num) + if pr == "error": + print("\n***ERROR*** Error in getting data for PR " + pr_num + "\n") + error_count += 1 + continue + rl_no_found = False + rl_yes_found = False + lang_found = False + for label in pr['labels']: + if label['name'] == 'release notes: yes': + rl_yes_found = True + elif label['name'] == 'release notes: no': + rl_no_found = True + elif label['name'].startswith('lang/'): + lang_found = True + lang = label['name'].split('/')[1].lower() + #lang = lang[0].upper() + lang[1:] + body = pr["title"] + if not body.endswith("."): + body = body + "." + if not pr["merged_by"]: + print("\n***ERROR***: No merge_by found for PR " + pr_num + "\n") + error_count += 1 + continue + + prline = "- " + body + " ([#" + pr_num + "](" + HTML_URL + pr_num + "))" + detail = "- " + pr["merged_by"]["login"] + "@ " + prline + prline = prline.encode('ascii', 'ignore') + detail = detail.encode('ascii', 'ignore') + print(detail) + #if no RL label + if not rl_no_found and not rl_yes_found: + print("Release notes label missing for " + pr_num) + langs_pr["nolabel"].append(detail) + elif rl_yes_found and not lang_found: + print("Lang label missing for " + pr_num) + langs_pr["nolang"].append(detail) + elif rl_no_found: + print("'Release notes:no' found for " + pr_num) + langs_pr["notinrel"].append(detail) + elif rl_yes_found: + print("'Release notes:yes' found for " + pr_num + " with lang " + + lang) + langs_pr["inrel"].append(detail) + langs_pr[lang].append(prline) + + return langs_pr, error_count + + +def write_draft(langs_pr, file, version, date): + file.write(content_header.format(version=version, date=date)) + file.write("PRs with missing release notes label - please fix in Github\n") + file.write("---\n") + file.write("\n") + if langs_pr["nolabel"]: + langs_pr["nolabel"].sort() + file.write("\n".join(langs_pr["nolabel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write("PRs with missing lang label - please fix in Github\n") + file.write("---\n") + file.write("\n") + if langs_pr["nolang"]: + langs_pr["nolang"].sort() + file.write("\n".join(langs_pr["nolang"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write( + "PRs going into release notes - please check title and fix in Github. Do not edit here.\n" + ) + file.write("---\n") + file.write("\n") + if langs_pr["inrel"]: + langs_pr["inrel"].sort() + file.write("\n".join(langs_pr["inrel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write("PRs not going into release notes\n") + file.write("---\n") + file.write("\n") + if langs_pr["notinrel"]: + langs_pr["notinrel"].sort() + file.write("\n".join(langs_pr["notinrel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + + +def write_rel_notes(langs_pr, file, version, name): + file.write(rl_header.format(version=version, name=name)) + if langs_pr["core"]: + file.write("Core\n---\n\n") + file.write("\n".join(langs_pr["core"])) + file.write("\n") + file.write("\n") + if langs_pr["c++"]: + file.write("C++\n---\n\n") + file.write("\n".join(langs_pr["c++"])) + file.write("\n") + file.write("\n") + if langs_pr["c#"]: + file.write("C#\n---\n\n") + file.write("\n".join(langs_pr["c#"])) + file.write("\n") + file.write("\n") + if langs_pr["go"]: + file.write("Go\n---\n\n") + file.write("\n".join(langs_pr["go"])) + file.write("\n") + file.write("\n") + if langs_pr["Java"]: + file.write("Java\n---\n\n") + file.write("\n".join(langs_pr["Java"])) + file.write("\n") + file.write("\n") + if langs_pr["node"]: + file.write("Node\n---\n\n") + file.write("\n".join(langs_pr["node"])) + file.write("\n") + file.write("\n") + if langs_pr["objc"]: + file.write("Objective-C\n---\n\n") + file.write("\n".join(langs_pr["objc"])) + file.write("\n") + file.write("\n") + if langs_pr["php"]: + file.write("PHP\n---\n\n") + file.write("\n".join(langs_pr["php"])) + file.write("\n") + file.write("\n") + if langs_pr["python"]: + file.write("Python\n---\n\n") + file.write("\n".join(langs_pr["python"])) + file.write("\n") + file.write("\n") + if langs_pr["ruby"]: + file.write("Ruby\n---\n\n") + file.write("\n".join(langs_pr["ruby"])) + file.write("\n") + file.write("\n") + if langs_pr["other"]: + file.write("Other\n---\n\n") + file.write("\n".join(langs_pr["other"])) + file.write("\n") + file.write("\n") + + +def build_args_parser(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument( + 'release_version', type=str, help='New release version e.g. 1.14.0') + parser.add_argument( + 'release_name', type=str, help='New release name e.g. gladiolus') + parser.add_argument( + 'release_date', type=str, help='Release date e.g. 7/30/18') + parser.add_argument( + 'previous_release_label', + type=str, + help='Previous release branch/tag e.g. v1.13.x') + parser.add_argument( + 'release_branch', + type=str, + help='Current release branch e.g. origin/v1.14.x') + parser.add_argument( + 'draft_filename', type=str, help='Name of the draft file e.g. draft.md') + parser.add_argument( + 'release_notes_filename', + type=str, + help='Name of the release notes file e.g. relnotes.md') + parser.add_argument( + '--token', + type=str, + default='', + help='GitHub API token to avoid being rate limited') + return parser + + +def main(): + import os + global TOKEN + + parser = build_args_parser() + args = parser.parse_args() + version, name, date = args.release_version, args.release_name, args.release_date + start, end = args.previous_release_label, args.release_branch + + TOKEN = args.token + if TOKEN == '': + try: + TOKEN = os.environ["GITHUB_TOKEN"] + except: + pass + if TOKEN == '': + print( + "Error: Github API token required. Either include param --token= or set environment variable GITHUB_TOKEN to your github token" + ) + return + + langs_pr, error_count = get_pr_titles(get_commit_log(start, end)) + + draft_file, rel_file = args.draft_filename, args.release_notes_filename + filename = os.path.abspath(draft_file) + if os.path.exists(filename): + file = open(filename, 'r+') + else: + file = open(filename, 'w') + + file.seek(0) + write_draft(langs_pr, file, version, date) + file.truncate() + file.close() + print("\nDraft notes written to " + filename) + + filename = os.path.abspath(rel_file) + if os.path.exists(filename): + file = open(filename, 'r+') + else: + file = open(filename, 'w') + + file.seek(0) + write_rel_notes(langs_pr, file, version, name) + file.truncate() + file.close() + print("\nRelease notes written to " + filename) + if error_count > 0: + print("\n\n*** Errors were encountered. See log. *********\n") + + +if __name__ == "__main__": + main() diff --git a/tools/remote_build/README.md b/tools/remote_build/README.md index 19739e9ee12..2cd5f03daf1 100644 --- a/tools/remote_build/README.md +++ b/tools/remote_build/README.md @@ -12,7 +12,7 @@ and tests run by Kokoro CI. - See [Installing Bazel](https://docs.bazel.build/versions/master/install.html) for instructions how to install bazel on your system. -- Setup application default credentials for running remote builds by following [RBE Credentials Setup](https://cloud.google.com/remote-build-execution/docs/getting-started#set_credentials) +- Setup application default credentials for running remote builds by following the ["Set credentials" section](https://cloud.google.com/remote-build-execution/docs/results-ui/getting-started-results-ui). (Note: for the ResultStore UI upload to work, you'll need a special kind of application default credentials, so if the build event upload doesn't work, doublecheck the instructions) ## Running remote build manually from dev workstation @@ -29,5 +29,11 @@ Sanitizer runs (asan, msan, tsan, ubsan): bazel --bazelrc=tools/remote_build/manual.bazelrc test --config=asan //test/... ``` +Run on Windows MSVC: +``` +# RBE manual run only for c-core (must be run on a Windows host machine) +bazel --bazelrc=tools/remote_build/windows.bazelrc build :all [--credentials_json=(path to service account credentials)] +``` + Available command line options can be found in [Bazel command line reference](https://docs.bazel.build/versions/master/command-line-reference.html) diff --git a/tools/remote_build/windows.bazelrc b/tools/remote_build/windows.bazelrc new file mode 100644 index 00000000000..492489f3613 --- /dev/null +++ b/tools/remote_build/windows.bazelrc @@ -0,0 +1,49 @@ +startup --host_jvm_args=-Dbazel.DigestFunction=SHA256 + +build --remote_cache=remotebuildexecution.googleapis.com +build --remote_executor=remotebuildexecution.googleapis.com +build --tls_enabled=true + +build --host_crosstool_top=//third_party/toolchains/bazel_0.23.2_rbe_windows:toolchain +build --crosstool_top=//third_party/toolchains/bazel_0.23.2_rbe_windows:toolchain +build --extra_toolchains=//third_party/toolchains/bazel_0.23.2_rbe_windows:cc-toolchain-x64_windows +# Use custom execution platforms defined in third_party/toolchains +build --extra_execution_platforms=//third_party/toolchains:rbe_windows +build --host_platform=//third_party/toolchains:rbe_windows +build --platforms=//third_party/toolchains:rbe_windows + +build --shell_executable=C:\\tools\\msys64\\usr\\bin\\bash.exe +build --python_path=C:\\Python27\\python.exe + +build --spawn_strategy=remote +build --strategy=Javac=remote +build --strategy=Closure=remote +build --genrule_strategy=remote +build --remote_timeout=3600 + +build --remote_instance_name=projects/grpc-testing/instances/grpc-windows-rbe-test + +build --verbose_failures=true + +build --experimental_strict_action_env=true +build --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 + +# don't use port server +build --define GRPC_PORT_ISOLATED_RUNTIME=1 +build --test_tag_filters=-no_windows +build --build_tag_filters=-no_windows + +# without verbose gRPC logs the test outputs are not very useful +test --test_env=GRPC_VERBOSITY=debug + +# Set flags for uploading to BES in order to view results in the Bazel Build +# Results UI. +build --bes_backend="buildeventservice.googleapis.com" +build --bes_timeout=60s +build --bes_results_url="https://source.cloud.google.com/results/invocations/" +build --project_id=grpc-testing + +build --jobs=30 + +# print output for tests that fail (default is "summary") +build --test_output=errors diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index cd88082f884..29fd6f32e59 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3715,6 +3715,27 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc++", + "grpc++_test", + "grpc_test_util" + ], + "headers": [ + "test/core/gprpp/map_tester.h" + ], + "is_filegroup": false, + "language": "c++", + "name": "grpc_core_map_test", + "src": [ + "test/core/gprpp/map_test.cc", + "test/core/gprpp/map_tester.h" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "grpc_plugin_support" @@ -4723,6 +4744,24 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "grpc", + "grpc++", + "grpc++_test", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c++", + "name": "service_config_test", + "src": [ + "test/core/client_channel/service_config_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -6585,6 +6624,7 @@ "headers": [ "include/grpc++/support/error_details.h", "include/grpcpp/support/error_details.h", + "include/grpcpp/support/error_details_impl.h", "src/proto/grpc/status/status.grpc.pb.h", "src/proto/grpc/status/status.pb.h", "src/proto/grpc/status/status_mock.grpc.pb.h" @@ -6595,6 +6635,7 @@ "src": [ "include/grpc++/support/error_details.h", "include/grpcpp/support/error_details.h", + "include/grpcpp/support/error_details_impl.h", "src/cpp/util/error_details.cc" ], "third_party": false, @@ -6629,6 +6670,7 @@ "headers": [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", "src/cpp/ext/proto_server_reflection.h" ], "is_filegroup": false, @@ -6637,6 +6679,7 @@ "src": [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", "src/cpp/ext/proto_server_reflection.cc", "src/cpp/ext/proto_server_reflection.h", "src/cpp/ext/proto_server_reflection_plugin.cc" @@ -6921,6 +6964,7 @@ ], "headers": [ "include/grpcpp/ext/channelz_service_plugin.h", + "include/grpcpp/ext/channelz_service_plugin_impl.h", "src/cpp/server/channelz/channelz_service.h" ], "is_filegroup": false, @@ -6928,6 +6972,7 @@ "name": "grpcpp_channelz", "src": [ "include/grpcpp/ext/channelz_service_plugin.h", + "include/grpcpp/ext/channelz_service_plugin_impl.h", "src/cpp/server/channelz/channelz_service.cc", "src/cpp/server/channelz/channelz_service.h", "src/cpp/server/channelz/channelz_service_plugin.cc" @@ -7986,8 +8031,10 @@ "src/core/lib/gprpp/atomic.h", "src/core/lib/gprpp/fork.h", "src/core/lib/gprpp/manual_constructor.h", + "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", "src/core/lib/gprpp/mutex_lock.h", + "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -8032,8 +8079,10 @@ "src/core/lib/gprpp/atomic.h", "src/core/lib/gprpp/fork.h", "src/core/lib/gprpp/manual_constructor.h", + "src/core/lib/gprpp/map.h", "src/core/lib/gprpp/memory.h", "src/core/lib/gprpp/mutex_lock.h", + "src/core/lib/gprpp/pair.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -10064,12 +10113,16 @@ "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", @@ -10080,18 +10133,25 @@ "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", + "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", + "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", @@ -10173,12 +10233,16 @@ "include/grpcpp/client_context.h", "include/grpcpp/completion_queue.h", "include/grpcpp/create_channel.h", + "include/grpcpp/create_channel_impl.h", "include/grpcpp/create_channel_posix.h", + "include/grpcpp/create_channel_posix_impl.h", "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", + "include/grpcpp/health_check_service_interface_impl.h", "include/grpcpp/impl/call.h", "include/grpcpp/impl/channel_argument_option.h", "include/grpcpp/impl/client_unary_call.h", @@ -10189,18 +10253,25 @@ "include/grpcpp/impl/rpc_service_method.h", "include/grpcpp/impl/serialization_traits.h", "include/grpcpp/impl/server_builder_option.h", + "include/grpcpp/impl/server_builder_option_impl.h", "include/grpcpp/impl/server_builder_plugin.h", "include/grpcpp/impl/server_initializer.h", + "include/grpcpp/impl/server_initializer_impl.h", "include/grpcpp/impl/service_type.h", "include/grpcpp/resource_quota.h", + "include/grpcpp/resource_quota_impl.h", "include/grpcpp/security/auth_context.h", "include/grpcpp/security/auth_metadata_processor.h", + "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", + "include/grpcpp/server_builder_impl.h", "include/grpcpp/server_context.h", "include/grpcpp/server_posix.h", + "include/grpcpp/server_posix_impl.h", "include/grpcpp/support/async_stream.h", "include/grpcpp/support/async_unary_call.h", "include/grpcpp/support/byte_buffer.h", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index cf0e574b09d..cfeff6fa838 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -4549,6 +4549,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "grpc_core_map_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": false + }, { "args": [], "benchmark": false, @@ -5349,6 +5373,30 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "service_config_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index d93add00cd2..785dff36eab 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -197,6 +197,7 @@ def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): inner_jobs=inner_jobs, timeout_seconds=_CPP_RUNTESTS_TIMEOUT) + # C# tests on .NET desktop/mono test_jobs += _generate_jobs( languages=['csharp'], configs=['dbg', 'opt'], @@ -204,6 +205,16 @@ def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): labels=['basictests', 'multilang'], extra_args=extra_args, inner_jobs=inner_jobs) + # C# tests on .NET core + test_jobs += _generate_jobs( + languages=['csharp'], + configs=['dbg', 'opt'], + platforms=['linux', 'macos', 'windows'], + arch='default', + compiler='coreclr', + labels=['basictests', 'multilang'], + extra_args=extra_args, + inner_jobs=inner_jobs) test_jobs += _generate_jobs( languages=['python'], @@ -392,16 +403,6 @@ def _create_portability_test_jobs(extra_args=[], extra_args=extra_args, inner_jobs=inner_jobs) - test_jobs += _generate_jobs( - languages=['csharp'], - configs=['dbg'], - platforms=['linux'], - arch='default', - compiler='coreclr', - labels=['portability', 'multilang'], - extra_args=extra_args, - inner_jobs=inner_jobs) - test_jobs += _generate_jobs( languages=['c'], configs=['dbg'],