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 562a71c2f29..b0c501455d1 100644 --- a/BUILD +++ b/BUILD @@ -256,6 +256,7 @@ GRPCXX_PUBLIC_HDRS = [ "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", @@ -524,6 +525,17 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc++_internal_hdrs_only", + hdrs = [ + "include/grpcpp/impl/codegen/sync.h", + ], + language = "c++", + deps = [ + "gpr_codegen", + ], +) + grpc_cc_library( name = "gpr_base", srcs = [ @@ -589,8 +601,8 @@ grpc_cc_library( "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/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h", ], @@ -2144,6 +2156,7 @@ grpc_cc_library( "include/grpcpp/impl/codegen/time.h", ], deps = [ + "grpc++_internal_hdrs_only", "grpc_codegen", ], ) @@ -2315,6 +2328,27 @@ 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 = [ @@ -2347,6 +2381,7 @@ grpc_cc_library( ":google_api_upb", ":proto_gen_validate_upb", ], + tags = ["no_windows"], ) grpc_cc_library( @@ -2454,3 +2489,11 @@ grpc_cc_library( ) 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 8fed27e202e..7f5157377a7 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -186,8 +186,8 @@ config("grpc_config") { "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/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/thd_posix.cc", "src/core/lib/gprpp/thd_windows.cc", @@ -1064,6 +1064,7 @@ config("grpc_config") { "include/grpcpp/impl/codegen/status_code_enum.h", "include/grpcpp/impl/codegen/string_ref.h", "include/grpcpp/impl/codegen/stub_options.h", + "include/grpcpp/impl/codegen/sync.h", "include/grpcpp/impl/codegen/sync_stream.h", "include/grpcpp/impl/codegen/time.h", "include/grpcpp/impl/grpc_library.h", @@ -1087,6 +1088,7 @@ config("grpc_config") { "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", @@ -1157,12 +1159,12 @@ config("grpc_config") { "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/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/http/format_request.h", "src/core/lib/http/httpcli.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a84523e5c92..cce21957659 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -699,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) @@ -3035,6 +3036,7 @@ foreach(_hdr 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 @@ -3179,6 +3181,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -3636,6 +3639,7 @@ foreach(_hdr 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 @@ -3780,6 +3784,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h include/grpc/census.h ) string(REPLACE "include/" "" _path ${_hdr}) @@ -4234,6 +4239,7 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4430,6 +4436,7 @@ foreach(_hdr include/grpc/impl/codegen/sync_generic.h include/grpc/impl/codegen/sync_posix.h include/grpc/impl/codegen/sync_windows.h + include/grpcpp/impl/codegen/sync.h include/grpc++/impl/codegen/proto_utils.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h @@ -4611,6 +4618,7 @@ foreach(_hdr 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 @@ -4755,6 +4763,7 @@ foreach(_hdr include/grpcpp/impl/codegen/stub_options.h include/grpcpp/impl/codegen/sync_stream.h include/grpcpp/impl/codegen/time.h + include/grpcpp/impl/codegen/sync.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) @@ -15752,6 +15761,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 d1158bf31ba..d972215250a 100644 --- a/Makefile +++ b/Makefile @@ -1262,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 @@ -1727,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 \ @@ -1869,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 \ @@ -2382,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" @@ -5366,6 +5371,7 @@ PUBLIC_HEADERS_CXX += \ 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 \ @@ -5510,6 +5516,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -5975,6 +5982,7 @@ PUBLIC_HEADERS_CXX += \ 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 \ @@ -6119,6 +6127,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc/census.h \ LIBGRPC++_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_CRONET_SRC)))) @@ -6545,6 +6554,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6712,6 +6722,7 @@ PUBLIC_HEADERS_CXX += \ include/grpc/impl/codegen/sync_generic.h \ include/grpc/impl/codegen/sync_posix.h \ include/grpc/impl/codegen/sync_windows.h \ + include/grpcpp/impl/codegen/sync.h \ include/grpc++/impl/codegen/proto_utils.h \ include/grpcpp/impl/codegen/proto_buffer_reader.h \ include/grpcpp/impl/codegen/proto_buffer_writer.h \ @@ -6899,6 +6910,7 @@ PUBLIC_HEADERS_CXX += \ 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 \ @@ -7043,6 +7055,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/impl/codegen/stub_options.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ + include/grpcpp/impl/codegen/sync.h \ LIBGRPC++_UNSECURE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_UNSECURE_SRC)))) @@ -18682,6 +18695,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 18f389edd24..b984438d1d6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -11,10 +11,12 @@ 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", ) # TODO(https://github.com/grpc/grpc/issues/18331): Move off of this dependency. diff --git a/build.yaml b/build.yaml index 888b613dc0e..9e78ec4efa3 100644 --- a/build.yaml +++ b/build.yaml @@ -196,8 +196,8 @@ filegroups: - 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/sync.h - src/core/lib/gprpp/thd.h - src/core/lib/profiling/timers.h uses: @@ -1276,6 +1276,7 @@ filegroups: - include/grpcpp/impl/codegen/time.h uses: - grpc_codegen + - grpc++_internal_hdrs_only - name: grpc++_codegen_base_src language: c++ src: @@ -1381,6 +1382,7 @@ filegroups: - 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 @@ -1449,6 +1451,7 @@ filegroups: - grpc_base_headers - grpc_transport_inproc_headers - grpc++_codegen_base + - grpc++_internal_hdrs_only - nanopb_headers - health_proto - name: grpc++_config_proto @@ -1456,6 +1459,10 @@ filegroups: public_headers: - include/grpc++/impl/codegen/config_protobuf.h - include/grpcpp/impl/codegen/config_protobuf.h +- name: grpc++_internal_hdrs_only + language: c++ + public_headers: + - include/grpcpp/impl/codegen/sync.h - name: grpc++_reflection_proto language: c++ src: @@ -5472,6 +5479,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/gRPC-C++.podspec b/gRPC-C++.podspec index 051397f1e67..b8e4d80b838 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -120,6 +120,7 @@ Pod::Spec.new do |s| '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', @@ -182,7 +183,8 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/string_ref.h', 'include/grpcpp/impl/codegen/stub_options.h', 'include/grpcpp/impl/codegen/sync_stream.h', - 'include/grpcpp/impl/codegen/time.h' + 'include/grpcpp/impl/codegen/time.h', + 'include/grpcpp/impl/codegen/sync.h' end s.subspec 'Implementation' do |ss| @@ -265,8 +267,8 @@ Pod::Spec.new do |s| '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/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', @@ -582,8 +584,8 @@ Pod::Spec.new do |s| '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/sync.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 bab7ce4378e..c58152cf7f8 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -210,8 +210,8 @@ Pod::Spec.new do |s| '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/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/lib/gpr/alloc.cc', @@ -889,8 +889,8 @@ Pod::Spec.new do |s| '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/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/profiling/timers.h', 'src/core/ext/transport/chttp2/transport/bin_decoder.h', diff --git a/grpc.gemspec b/grpc.gemspec index b9d2107ee48..c41db6f6293 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -104,8 +104,8 @@ Gem::Specification.new do |s| 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/sync.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/grpcpp/channel.h b/include/grpcpp/channel.h index ee833960698..c4d5ab1177b 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -28,6 +28,7 @@ #include #include #include +#include struct grpc_channel; @@ -97,7 +98,7 @@ class Channel final : public ChannelInterface, grpc_channel* const c_channel_; // owned // mu_ protects callback_cq_ (the per-channel callbackable completion queue) - std::mutex mu_; + grpc::internal::Mutex mu_; // callback_cq_ references the callbackable completion queue associated // with this channel (if any). It is set on the first call to CallbackCQ(). diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 5946488566e..85bbf36f06d 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -51,6 +51,7 @@ #include #include #include +#include #include struct census_context; @@ -457,7 +458,7 @@ class ClientContext { bool idempotent_; bool cacheable_; std::shared_ptr channel_; - std::mutex mu_; + grpc::internal::Mutex mu_; grpc_call* call_; bool call_canceled_; gpr_timespec deadline_; 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 87edea84f41..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 @@ -253,7 +285,9 @@ class ServerBidiReactor : public internal::ServerReactor { void Finish(Status s) { stream_->Finish(std::move(s)); } /// Notify the application that a streaming RPC has started and that it is now - /// ok to call any operation initation method. + /// 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) {} @@ -588,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(); } @@ -730,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(); } @@ -906,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/sync.h b/include/grpcpp/impl/codegen/sync.h new file mode 100644 index 00000000000..2ed71eeb9f2 --- /dev/null +++ b/include/grpcpp/impl/codegen/sync.h @@ -0,0 +1,138 @@ +/* + * + * 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_IMPL_CODEGEN_SYNC_H +#define GRPCPP_IMPL_CODEGEN_SYNC_H + +#include +#include +#include + +#include + +// The core library is not accessible in C++ codegen headers, and vice versa. +// Thus, we need to have duplicate headers with similar functionality. +// Make sure any change to this file is also reflected in +// src/core/lib/gprpp/sync.h too. +// +// Whenever possible, prefer "src/core/lib/gprpp/sync.h" over this file, +// since in core we do not rely on g_core_codegen_interface and hence do not +// pay the costs of virtual function calls. + +namespace grpc { +namespace internal { + +class Mutex { + public: + Mutex() { g_core_codegen_interface->gpr_mu_init(&mu_); } + ~Mutex() { g_core_codegen_interface->gpr_mu_destroy(&mu_); } + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + gpr_mu* get() { return &mu_; } + const gpr_mu* get() const { return &mu_; } + + private: + gpr_mu mu_; +}; + +// MutexLock is a std:: +class MutexLock { + public: + explicit MutexLock(Mutex* mu) : mu_(mu->get()) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + explicit MutexLock(gpr_mu* mu) : mu_(mu) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + ~MutexLock() { g_core_codegen_interface->gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +class ReleasableMutexLock { + public: + explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { + g_core_codegen_interface->gpr_mu_lock(mu_); + } + ~ReleasableMutexLock() { + if (!released_) g_core_codegen_interface->gpr_mu_unlock(mu_); + } + + ReleasableMutexLock(const ReleasableMutexLock&) = delete; + ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; + + void Lock() { + GPR_DEBUG_ASSERT(released_); + g_core_codegen_interface->gpr_mu_lock(mu_); + released_ = false; + } + + void Unlock() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + g_core_codegen_interface->gpr_mu_unlock(mu_); + } + + private: + gpr_mu* const mu_; + bool released_ = false; +}; + +class CondVar { + public: + CondVar() { g_core_codegen_interface->gpr_cv_init(&cv_); } + ~CondVar() { g_core_codegen_interface->gpr_cv_destroy(&cv_); } + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Signal() { g_core_codegen_interface->gpr_cv_signal(&cv_); } + void Broadcast() { g_core_codegen_interface->gpr_cv_broadcast(&cv_); } + + int Wait(Mutex* mu) { + return Wait(mu, + g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); + } + int Wait(Mutex* mu, const gpr_timespec& deadline) { + return g_core_codegen_interface->gpr_cv_wait(&cv_, mu->get(), deadline); + } + + template + void WaitUntil(Mutex* mu, Predicate pred) { + while (!pred()) { + Wait(mu, g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + + private: + gpr_cv cv_; +}; + +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_CODEGEN_SYNC_H diff --git a/include/grpcpp/impl/server_builder_plugin.h b/include/grpcpp/impl/server_builder_plugin.h index adde29da7d1..dd600a839d7 100644 --- a/include/grpcpp/impl/server_builder_plugin.h +++ b/include/grpcpp/impl/server_builder_plugin.h @@ -25,11 +25,11 @@ namespace grpc_impl { +class ServerBuilder; class ServerInitializer; -} +} // namespace grpc_impl namespace grpc { -class ServerBuilder; class ChannelArguments; /// This interface is meant for internal usage only. Implementations of this @@ -43,7 +43,7 @@ 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. diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h index e0fddbf1bc8..afe8d22650b 100644 --- a/include/grpcpp/security/server_credentials_impl.h +++ b/include/grpcpp/security/server_credentials_impl.h @@ -51,7 +51,7 @@ class ServerCredentials { /// 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. + /// \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; diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index ac69131cc82..8aff0663fe2 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -201,7 +201,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { } friend class AsyncGenericService; - friend class ServerBuilder; + friend class grpc_impl::ServerBuilder; friend class grpc_impl::ServerInitializer; class SyncRequest; @@ -297,12 +297,12 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { experimental_registration_type experimental_registration_{this}; // Server status - std::mutex mu_; + grpc::internal::Mutex mu_; bool started_; bool shutdown_; bool shutdown_notified_; // Was notify called on the shutdown_cv_ - std::condition_variable shutdown_cv_; + grpc::internal::CondVar 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 @@ -311,8 +311,8 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // 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_; + grpc::internal::Mutex callback_reqs_mu_; + grpc::internal::CondVar callback_reqs_done_cv_; std::atomic_int callback_reqs_outstanding_{0}; std::shared_ptr global_callbacks_; diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index bd8fa4621f7..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,21 +19,7 @@ #ifndef GRPCPP_SERVER_BUILDER_H #define GRPCPP_SERVER_BUILDER_H -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -struct grpc_resource_quota; +#include namespace grpc_impl { @@ -43,305 +29,7 @@ class ResourceQuota; namespace grpc { -class AsyncGenericService; -class CompletionQueue; -class Server; -class ServerCompletionQueue; -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 ::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(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_; - - /// List of completion queues added via \a AddCompletionQueue method. - std::vector cqs_; - - 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..14b16a06f4e --- /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 + grpc::internal::Mutex mu_; + bool started_; + bool shutdown_; + bool shutdown_notified_; // Was notify called on the shutdown_cv_ + + grpc::internal::CondVar 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. + grpc::internal::Mutex callback_reqs_mu_; + grpc::internal::CondVar 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/package.xml b/package.xml index f3bbb449ac5..5be3d24365d 100644 --- a/package.xml +++ b/package.xml @@ -109,8 +109,8 @@ - + 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/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 86938a51d9b..cd552739732 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -51,7 +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/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" 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 a22d6450cbd..a99f1e54062 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 @@ -27,7 +27,7 @@ #include "pb_encode.h" #include "src/core/ext/filters/client_channel/health/health.pb.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/status_metadata.h" @@ -69,7 +69,6 @@ HealthCheckClient::HealthCheckClient( } GRPC_CLOSURE_INIT(&retry_timer_callback_, OnRetryTimer, this, grpc_schedule_on_exec_ctx); - gpr_mu_init(&mu_); StartCall(); } @@ -78,7 +77,6 @@ HealthCheckClient::~HealthCheckClient() { gpr_log(GPR_INFO, "destroying HealthCheckClient %p", this); } GRPC_ERROR_UNREF(error_); - gpr_mu_destroy(&mu_); } void HealthCheckClient::NotifyOnHealthChange(grpc_connectivity_state* state, 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 1fa4487c403..6e0123e4925 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 @@ -31,6 +31,7 @@ #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/gprpp/sync.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -157,7 +158,7 @@ class HealthCheckClient : public InternallyRefCounted { grpc_pollset_set* interested_parties_; // Do not own. RefCountedPtr channelz_node_; - gpr_mu mu_; + Mutex mu_; grpc_connectivity_state state_ = GRPC_CHANNEL_CONNECTING; grpc_error* error_ = GRPC_ERROR_NONE; grpc_connectivity_state* notify_state_ = nullptr; diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 2b1eb92bbd4..90a79843458 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -33,7 +33,7 @@ #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/slice/slice_internal.h" 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 aebd2fd3faa..ead15308f49 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 @@ -88,7 +88,6 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/combiner.h" 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 84b9c41a734..35123633feb 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,7 +25,7 @@ #include #include -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { 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 fdebdf55c17..bcc6598c105 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 @@ -26,6 +26,7 @@ #include "src/core/lib/gprpp/inlined_vector.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { @@ -41,9 +42,6 @@ class GrpcLbClientStats : public RefCounted { typedef InlinedVector DroppedCallCounts; - 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); @@ -66,7 +64,7 @@ class GrpcLbClientStats : public RefCounted { 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_. + Mutex drop_count_mu_; // Guards drop_token_counts_. UniquePtr drop_token_counts_; }; 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 332f66808e0..892472e1c9b 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 @@ -27,7 +27,7 @@ #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -154,13 +154,12 @@ class PickFirst : public LoadBalancingPolicy { /// Lock and data used to capture snapshots of this channels child /// channels and subchannels. This data is consumed by channelz. - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; PickFirst::PickFirst(Args args) : LoadBalancingPolicy(std::move(args)) { - gpr_mu_init(&child_refs_mu_); if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Pick First %p created.", this); } @@ -170,7 +169,6 @@ PickFirst::~PickFirst() { if (grpc_lb_pick_first_trace.enabled()) { gpr_log(GPR_INFO, "Destroying Pick First %p", this); } - gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index d3faaaddc98..29cfe972f78 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -36,8 +36,8 @@ #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" @@ -193,7 +193,7 @@ class RoundRobin : public LoadBalancingPolicy { bool shutdown_ = false; /// Lock and data used to capture snapshots of this channel's child /// channels and subchannels. This data is consumed by channelz. - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; channelz::ChildRefsList child_subchannels_; channelz::ChildRefsList child_channels_; }; @@ -245,7 +245,6 @@ RoundRobin::PickResult RoundRobin::Picker::Pick(PickArgs* pick, // RoundRobin::RoundRobin(Args args) : LoadBalancingPolicy(std::move(args)) { - gpr_mu_init(&child_refs_mu_); if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Created", this); } @@ -255,7 +254,6 @@ RoundRobin::~RoundRobin() { if (grpc_lb_round_robin_trace.enabled()) { gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this); } - gpr_mu_destroy(&child_refs_mu_); GPR_ASSERT(subchannel_list_ == nullptr); GPR_ASSERT(latest_pending_subchannel_list_ == nullptr); } 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 fe49e9aca03..443deb01274 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 @@ -89,9 +89,9 @@ #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" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -278,10 +278,8 @@ class XdsLb : public LoadBalancingPolicy { 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_); } + : parent_(std::move(parent)) {} + ~LocalityEntry() = default; void UpdateLocked(xds_grpclb_serverlist* serverlist, LoadBalancingPolicy::Config* child_policy_config, @@ -323,13 +321,10 @@ class XdsLb : public LoadBalancingPolicy { OrphanablePtr pending_child_policy_; // Lock held when modifying the value of child_policy_ or // pending_child_policy_. - gpr_mu child_policy_mu_; + Mutex child_policy_mu_; RefCountedPtr parent_; }; - LocalityMap() { gpr_mu_init(&child_refs_mu_); } - ~LocalityMap() { gpr_mu_destroy(&child_refs_mu_); } - void UpdateLocked(const LocalityList& locality_list, LoadBalancingPolicy::Config* child_policy_config, const grpc_channel_args* args, XdsLb* parent); @@ -343,7 +338,7 @@ class XdsLb : public LoadBalancingPolicy { Map, OrphanablePtr, StringLess> map_; // Lock held while filling child refs for all localities // inside the map - gpr_mu child_refs_mu_; + Mutex child_refs_mu_; }; struct LocalityServerlistEntry { @@ -397,7 +392,7 @@ class XdsLb : public LoadBalancingPolicy { // Mutex to protect the channel to the LB server. This is used when // processing a channelz request. // TODO(juanlishen): Replace this with atomic. - gpr_mu lb_chand_mu_; + Mutex lb_chand_mu_; // Timeout in milliseconds for the LB call. 0 means no deadline. int lb_call_timeout_ms_ = 0; @@ -1090,7 +1085,6 @@ XdsLb::XdsLb(Args args) : LoadBalancingPolicy(std::move(args)), locality_map_(), locality_serverlist_() { - gpr_mu_init(&lb_chand_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); @@ -1114,7 +1108,6 @@ XdsLb::XdsLb(Args args) } XdsLb::~XdsLb() { - gpr_mu_destroy(&lb_chand_mu_); gpr_free((void*)server_name_); grpc_channel_args_destroy(args_); locality_serverlist_.clear(); 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..7b5eb311393 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 @@ -308,7 +308,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); } 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/resolving_lb_policy.cc b/src/core/ext/filters/client_channel/resolving_lb_policy.cc index d15af908b3f..a2367e09d9b 100644 --- a/src/core/ext/filters/client_channel/resolving_lb_policy.cc +++ b/src/core/ext/filters/client_channel/resolving_lb_policy.cc @@ -48,7 +48,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/gprpp/sync.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" 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..b38bd4b701e 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -42,8 +42,8 @@ #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/manual_constructor.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -457,13 +457,14 @@ struct Subchannel::ExternalStateWatcher { grpc_pollset_set_del_pollset_set(w->subchannel->pollset_set_, w->pollset_set); } - gpr_mu_lock(&w->subchannel->mu_); - if (w->subchannel->external_state_watcher_list_ == w) { - w->subchannel->external_state_watcher_list_ = w->next; + { + MutexLock lock(&w->subchannel->mu_); + if (w->subchannel->external_state_watcher_list_ == w) { + w->subchannel->external_state_watcher_list_ = w->next; + } + if (w->next != nullptr) w->next->prev = w->prev; + if (w->prev != nullptr) w->prev->next = w->next; } - if (w->next != nullptr) w->next->prev = w->prev; - if (w->prev != nullptr) w->prev->next = w->next; - gpr_mu_unlock(&w->subchannel->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(w->subchannel, "external_state_watcher+done"); Delete(w); GRPC_CLOSURE_SCHED(follow_up, GRPC_ERROR_REF(error)); @@ -585,13 +586,15 @@ Subchannel::Subchannel(SubchannelKey* key, grpc_connector* connector, "subchannel"); grpc_connectivity_state_init(&state_and_health_tracker_, GRPC_CHANNEL_IDLE, "subchannel"); - gpr_mu_init(&mu_); // Check whether we should enable health checking. 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); @@ -629,7 +632,6 @@ Subchannel::~Subchannel() { grpc_connector_unref(connector_); grpc_pollset_set_destroy(pollset_set_); Delete(key_); - gpr_mu_destroy(&mu_); } Subchannel* Subchannel::Create(grpc_connector* connector, @@ -905,7 +907,9 @@ void Subchannel::MaybeStartConnectingLocked() { void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { Subchannel* c = static_cast(arg); - gpr_mu_lock(&c->mu_); + // TODO(soheilhy): Once subchannel refcounting is simplified, we can get use + // MutexLock instead of ReleasableMutexLock, here. + ReleasableMutexLock lock(&c->mu_); c->have_retry_alarm_ = false; if (c->disconnected_) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", @@ -919,9 +923,9 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { if (error == GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); c->ContinueConnectingLocked(); - gpr_mu_unlock(&c->mu_); + lock.Unlock(); } else { - gpr_mu_unlock(&c->mu_); + lock.Unlock(); GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } GRPC_ERROR_UNREF(error); @@ -948,29 +952,30 @@ void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { auto* c = static_cast(arg); grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); - gpr_mu_lock(&c->mu_); - c->connecting_ = false; - if (c->connecting_result_.transport != nullptr && - c->PublishTransportLocked()) { - // Do nothing, transport was published. - } else if (c->disconnected_) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - const char* errmsg = grpc_error_string(error); - gpr_log(GPR_INFO, "Connect failed: %s", errmsg); - error = - grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Connect Failed", &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); - c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, - GRPC_ERROR_REF(error), "connect_failed"); - grpc_connectivity_state_set(&c->state_and_health_tracker_, - GRPC_CHANNEL_TRANSIENT_FAILURE, error, - "connect_failed"); - c->MaybeStartConnectingLocked(); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + { + MutexLock lock(&c->mu_); + c->connecting_ = false; + if (c->connecting_result_.transport != nullptr && + c->PublishTransportLocked()) { + // Do nothing, transport was published. + } else if (c->disconnected_) { + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } else { + const char* errmsg = grpc_error_string(error); + gpr_log(GPR_INFO, "Connect failed: %s", errmsg); + error = grpc_error_set_int( + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Connect Failed", + &error, 1), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, + GRPC_ERROR_REF(error), "connect_failed"); + grpc_connectivity_state_set(&c->state_and_health_tracker_, + GRPC_CHANNEL_TRANSIENT_FAILURE, error, + "connect_failed"); + c->MaybeStartConnectingLocked(); + GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + } } - gpr_mu_unlock(&c->mu_); GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); grpc_channel_args_destroy(delete_channel_args); } diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 968fc74e22a..83b57dd7ff3 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -29,6 +29,7 @@ #include "src/core/lib/gpr/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/connectivity_state.h" @@ -264,7 +265,7 @@ class Subchannel { // pollset_set tracking who's interested in a connection being setup. grpc_pollset_set* pollset_set_; // Protects the other members. - gpr_mu mu_; + Mutex mu_; // Refcount // - lower INTERNAL_REF_BITS bits are for internal references: // these do not keep the subchannel open. 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/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/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 9f0169aeaab..b6a660b18fd 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -23,7 +23,7 @@ #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include #include diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index 912d524c8db..b68799b6e0e 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -27,8 +27,8 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/inlined_vector.h" -#include "src/core/lib/gprpp/mutex_lock.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/exec_ctx.h" diff --git a/src/core/lib/gprpp/mutex_lock.h b/src/core/lib/gprpp/mutex_lock.h deleted file mode 100644 index 54751d5fe46..00000000000 --- a/src/core/lib/gprpp/mutex_lock.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * 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 GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H -#define GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H - -#include - -#include - -namespace grpc_core { - -class MutexLock { - public: - explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu); } - ~MutexLock() { gpr_mu_unlock(mu_); } - - MutexLock(const MutexLock&) = delete; - MutexLock& operator=(const MutexLock&) = delete; - - private: - gpr_mu* const mu_; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_LIB_GPRPP_MUTEX_LOCK_H */ diff --git a/src/core/lib/gprpp/sync.h b/src/core/lib/gprpp/sync.h new file mode 100644 index 00000000000..895ca60fec0 --- /dev/null +++ b/src/core/lib/gprpp/sync.h @@ -0,0 +1,126 @@ +/* + * + * 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 GRPC_CORE_LIB_GPRPP_SYNC_H +#define GRPC_CORE_LIB_GPRPP_SYNC_H + +#include + +#include +#include +#include +#include + +// The core library is not accessible in C++ codegen headers, and vice versa. +// Thus, we need to have duplicate headers with similar functionality. +// Make sure any change to this file is also reflected in +// include/grpcpp/impl/codegen/sync.h. +// +// Whenever possible, prefer using this file over +// since this file doesn't rely on g_core_codegen_interface and hence does not +// pay the costs of virtual function calls. + +namespace grpc_core { + +class Mutex { + public: + Mutex() { gpr_mu_init(&mu_); } + ~Mutex() { gpr_mu_destroy(&mu_); } + + Mutex(const Mutex&) = delete; + Mutex& operator=(const Mutex&) = delete; + + gpr_mu* get() { return &mu_; } + const gpr_mu* get() const { return &mu_; } + + private: + gpr_mu mu_; +}; + +// MutexLock is a std:: +class MutexLock { + public: + explicit MutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } + explicit MutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~MutexLock() { gpr_mu_unlock(mu_); } + + MutexLock(const MutexLock&) = delete; + MutexLock& operator=(const MutexLock&) = delete; + + private: + gpr_mu* const mu_; +}; + +class ReleasableMutexLock { + public: + explicit ReleasableMutexLock(Mutex* mu) : mu_(mu->get()) { gpr_mu_lock(mu_); } + explicit ReleasableMutexLock(gpr_mu* mu) : mu_(mu) { gpr_mu_lock(mu_); } + ~ReleasableMutexLock() { + if (!released_) gpr_mu_unlock(mu_); + } + + ReleasableMutexLock(const ReleasableMutexLock&) = delete; + ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete; + + void Lock() { + GPR_DEBUG_ASSERT(released_); + gpr_mu_lock(mu_); + released_ = false; + } + + void Unlock() { + GPR_DEBUG_ASSERT(!released_); + released_ = true; + gpr_mu_unlock(mu_); + } + + private: + gpr_mu* const mu_; + bool released_ = false; +}; + +class CondVar { + public: + CondVar() { gpr_cv_init(&cv_); } + ~CondVar() { gpr_cv_destroy(&cv_); } + + CondVar(const CondVar&) = delete; + CondVar& operator=(const CondVar&) = delete; + + void Signal() { gpr_cv_signal(&cv_); } + void Broadcast() { gpr_cv_broadcast(&cv_); } + + int Wait(Mutex* mu) { return Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); } + int Wait(Mutex* mu, const gpr_timespec& deadline) { + return gpr_cv_wait(&cv_, mu->get(), deadline); + } + + template + void WaitUntil(Mutex* mu, Predicate pred) { + while (!pred()) { + Wait(mu, gpr_inf_future(GPR_CLOCK_REALTIME)); + } + } + + private: + gpr_cv cv_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_GPRPP_SYNC_H */ diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index 01be46c9f68..c387f8359a0 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -47,7 +47,7 @@ #include "src/core/lib/gpr/useful.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/gprpp/sync.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/is_epollexclusive_available.h" 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/surface/init.cc b/src/core/lib/surface/init.cc index b67d4f12252..57d975564b1 100644 --- a/src/core/lib/surface/init.cc +++ b/src/core/lib/surface/init.cc @@ -33,7 +33,7 @@ #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/fork.h" -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/parser.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/combiner.h" diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc index f9184bcc34f..ba0745a2359 100644 --- a/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.cc @@ -18,7 +18,7 @@ #include -#include "src/core/lib/gprpp/mutex_lock.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/tsi/ssl/session_cache/ssl_session.h" #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index db59d4d8416..2d5e74163a9 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -232,7 +232,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered - std::lock_guard l(mu_); + grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index efb59c71a8c..b4fce79b99a 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -84,7 +85,7 @@ void ClientContext::AddMetadata(const grpc::string& meta_key, void ClientContext::set_call(grpc_call* call, const std::shared_ptr& channel) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); GPR_ASSERT(call_ == nullptr); call_ = call; channel_ = channel; @@ -114,7 +115,7 @@ void ClientContext::set_compression_algorithm( } void ClientContext::TryCancel() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (call_) { SendCancelToInterceptors(); grpc_call_cancel(call_, nullptr); diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 9426a4e7f6e..e1dca5f1a12 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -79,9 +79,7 @@ std::shared_ptr CreateCustomChannelWithInterceptors( grpc_lame_client_channel_create( nullptr, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials."), - std::vector>()); + std::move(interceptor_creators)); } } // namespace experimental diff --git a/src/cpp/server/dynamic_thread_pool.cc b/src/cpp/server/dynamic_thread_pool.cc index ef99d6459f7..c8bdbdea7e6 100644 --- a/src/cpp/server/dynamic_thread_pool.cc +++ b/src/cpp/server/dynamic_thread_pool.cc @@ -21,6 +21,7 @@ #include #include +#include #include "src/core/lib/gprpp/thd.h" @@ -40,27 +41,27 @@ DynamicThreadPool::DynamicThread::~DynamicThread() { thd_.Join(); } void DynamicThreadPool::DynamicThread::ThreadFunc() { pool_->ThreadFunc(); // Now that we have killed ourselves, we should reduce the thread count - std::unique_lock lock(pool_->mu_); + grpc_core::MutexLock lock(&pool_->mu_); pool_->nthreads_--; // Move ourselves to dead list pool_->dead_threads_.push_back(this); if ((pool_->shutdown_) && (pool_->nthreads_ == 0)) { - pool_->shutdown_cv_.notify_one(); + pool_->shutdown_cv_.Signal(); } } void DynamicThreadPool::ThreadFunc() { for (;;) { // Wait until work is available or we are shutting down. - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); if (!shutdown_ && callbacks_.empty()) { // If there are too many threads waiting, then quit this thread if (threads_waiting_ >= reserve_threads_) { break; } threads_waiting_++; - cv_.wait(lock); + cv_.Wait(&mu_); threads_waiting_--; } // Drain callbacks before considering shutdown to ensure all work @@ -68,7 +69,7 @@ void DynamicThreadPool::ThreadFunc() { if (!callbacks_.empty()) { auto cb = callbacks_.front(); callbacks_.pop(); - lock.unlock(); + lock.Unlock(); cb(); } else if (shutdown_) { break; @@ -82,7 +83,7 @@ DynamicThreadPool::DynamicThreadPool(int reserve_threads) nthreads_(0), threads_waiting_(0) { for (int i = 0; i < reserve_threads_; i++) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); nthreads_++; new DynamicThread(this); } @@ -95,17 +96,17 @@ void DynamicThreadPool::ReapThreads(std::list* tlist) { } DynamicThreadPool::~DynamicThreadPool() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); shutdown_ = true; - cv_.notify_all(); + cv_.Broadcast(); while (nthreads_ != 0) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } ReapThreads(&dead_threads_); } void DynamicThreadPool::Add(const std::function& callback) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); // Add works to the callbacks list callbacks_.push(callback); // Increase pool size or notify as needed @@ -114,7 +115,7 @@ void DynamicThreadPool::Add(const std::function& callback) { nthreads_++; new DynamicThread(this); } else { - cv_.notify_one(); + cv_.Signal(); } // Also use this chance to harvest dead threads if (!dead_threads_.empty()) { diff --git a/src/cpp/server/dynamic_thread_pool.h b/src/cpp/server/dynamic_thread_pool.h index 5df8cf2b043..4ae0257d40b 100644 --- a/src/cpp/server/dynamic_thread_pool.h +++ b/src/cpp/server/dynamic_thread_pool.h @@ -27,6 +27,7 @@ #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/thread_pool_interface.h" @@ -50,9 +51,9 @@ class DynamicThreadPool final : public ThreadPoolInterface { grpc_core::Thread thd_; void ThreadFunc(); }; - std::mutex mu_; - std::condition_variable cv_; - std::condition_variable shutdown_cv_; + grpc_core::Mutex mu_; + grpc_core::CondVar cv_; + grpc_core::CondVar shutdown_cv_; bool shutdown_; std::queue> callbacks_; int reserve_threads_; diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc index 44aebd2f9d9..01bc51aa213 100644 --- a/src/cpp/server/health/default_health_check_service.cc +++ b/src/cpp/server/health/default_health_check_service.cc @@ -41,7 +41,7 @@ DefaultHealthCheckService::DefaultHealthCheckService() { void DefaultHealthCheckService::SetServingStatus( const grpc::string& service_name, bool serving) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { // Set to NOT_SERVING in case service_name is not in the map. serving = false; @@ -51,7 +51,7 @@ void DefaultHealthCheckService::SetServingStatus( void DefaultHealthCheckService::SetServingStatus(bool serving) { const ServingStatus status = serving ? SERVING : NOT_SERVING; - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -62,7 +62,7 @@ void DefaultHealthCheckService::SetServingStatus(bool serving) { } void DefaultHealthCheckService::Shutdown() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -76,7 +76,7 @@ void DefaultHealthCheckService::Shutdown() { DefaultHealthCheckService::ServingStatus DefaultHealthCheckService::GetServingStatus( const grpc::string& service_name) const { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) { return NOT_FOUND; @@ -88,7 +88,7 @@ DefaultHealthCheckService::GetServingStatus( void DefaultHealthCheckService::RegisterCallHandler( const grpc::string& service_name, std::shared_ptr handler) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); ServiceData& service_data = services_map_[service_name]; service_data.AddCallHandler(handler /* copies ref */); HealthCheckServiceImpl::CallHandler* h = handler.get(); @@ -98,7 +98,7 @@ void DefaultHealthCheckService::RegisterCallHandler( void DefaultHealthCheckService::UnregisterCallHandler( const grpc::string& service_name, const std::shared_ptr& handler) { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); auto it = services_map_.find(service_name); if (it == services_map_.end()) return; ServiceData& service_data = it->second; @@ -166,7 +166,7 @@ DefaultHealthCheckService::HealthCheckServiceImpl::~HealthCheckServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); cq_->Shutdown(); } thread_->Join(); @@ -266,7 +266,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: std::make_shared(cq, database, service); CheckCallHandler* handler = static_cast(self.get()); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; // Request a Check() call. handler->next_ = @@ -311,7 +311,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler:: } // Send response. { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); if (!service_->shutdown_) { next_ = CallableTag(std::bind(&CheckCallHandler::OnFinishDone, this, @@ -347,7 +347,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: std::make_shared(cq, database, service); WatchCallHandler* handler = static_cast(self.get()); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; // Request AsyncNotifyWhenDone(). handler->on_done_notified_ = @@ -402,7 +402,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendHealth(std::shared_ptr self, ServingStatus status) { - std::unique_lock lock(send_mu_); + grpc_core::MutexLock lock(&send_mu_); // If there's already a send in flight, cache the new status, and // we'll start a new send for it when the one in flight completes. if (send_in_flight_) { @@ -420,7 +420,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: ByteBuffer response; bool success = service_->EncodeResponse(status, &response); // Grab shutdown lock and send response. - std::unique_lock cq_lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { SendFinishLocked(std::move(self), Status::CANCELLED); return; @@ -442,7 +442,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::move(self), Status::CANCELLED); return; } - std::unique_lock lock(send_mu_); + grpc_core::MutexLock lock(&send_mu_); send_in_flight_ = false; // If we got a new status since we started the last send, start a // new send for it. @@ -456,7 +456,7 @@ void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler:: SendFinish(std::shared_ptr self, const Status& status) { if (finish_called_) return; - std::unique_lock cq_lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock cq_lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) return; SendFinishLocked(std::move(self), status); } diff --git a/src/cpp/server/health/default_health_check_service.h b/src/cpp/server/health/default_health_check_service.h index 9551cd2e2cf..4b926efdfe8 100644 --- a/src/cpp/server/health/default_health_check_service.h +++ b/src/cpp/server/health/default_health_check_service.h @@ -31,6 +31,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" namespace grpc { @@ -197,7 +198,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { GenericServerAsyncWriter stream_; ServerContext ctx_; - std::mutex send_mu_; + grpc_core::Mutex send_mu_; bool send_in_flight_ = false; // Guarded by mu_. ServingStatus pending_status_ = NOT_FOUND; // Guarded by mu_. @@ -226,7 +227,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { // To synchronize the operations related to shutdown state of cq_, so that // we don't enqueue new tags into cq_ after it is already shut down. - std::mutex cq_shutdown_mu_; + grpc_core::Mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; }; @@ -273,7 +274,7 @@ class DefaultHealthCheckService final : public HealthCheckServiceInterface { const grpc::string& service_name, const std::shared_ptr& handler); - mutable std::mutex mu_; + mutable grpc_core::Mutex mu_; bool shutdown_ = false; // Guarded by mu_. std::map services_map_; // Guarded by mu_. std::unique_ptr impl_; diff --git a/src/cpp/server/load_reporter/load_reporter.cc b/src/cpp/server/load_reporter/load_reporter.cc index 464063a13ff..422ea62efd5 100644 --- a/src/cpp/server/load_reporter/load_reporter.cc +++ b/src/cpp/server/load_reporter/load_reporter.cc @@ -239,7 +239,7 @@ grpc::string LoadReporter::GenerateLbId() { ::grpc::lb::v1::LoadBalancingFeedback LoadReporter::GenerateLoadBalancingFeedback() { - std::unique_lock lock(feedback_mu_); + grpc_core::ReleasableMutexLock lock(&feedback_mu_); auto now = std::chrono::system_clock::now(); // Discard records outside the window until there is only one record // outside the window, which is used as the base for difference. @@ -277,7 +277,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { double cpu_limit = newest->cpu_limit - oldest->cpu_limit; std::chrono::duration duration_seconds = newest->end_time - oldest->end_time; - lock.unlock(); + lock.Unlock(); ::grpc::lb::v1::LoadBalancingFeedback feedback; feedback.set_server_utilization(static_cast(cpu_usage / cpu_limit)); feedback.set_calls_per_second( @@ -290,7 +290,7 @@ LoadReporter::GenerateLoadBalancingFeedback() { ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> LoadReporter::GenerateLoads(const grpc::string& hostname, const grpc::string& lb_id) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); auto assigned_stores = load_data_store_.GetAssignedStores(hostname, lb_id); GPR_ASSERT(assigned_stores != nullptr); GPR_ASSERT(!assigned_stores->empty()); @@ -371,7 +371,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { // This will make the load balancing feedback generation a no-op. cpu_stats = {0, 0}; } - std::unique_lock lock(feedback_mu_); + grpc_core::MutexLock lock(&feedback_mu_); feedback_records_.emplace_back(std::chrono::system_clock::now(), rpcs, errors, cpu_stats.first, cpu_stats.second); } @@ -379,7 +379,7 @@ void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) { void LoadReporter::ReportStreamCreated(const grpc::string& hostname, const grpc::string& lb_id, const grpc::string& load_key) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.ReportStreamCreated(hostname, lb_id, load_key); gpr_log(GPR_INFO, "[LR %p] Report stream created (host: %s, LB ID: %s, load key: %s).", @@ -388,7 +388,7 @@ void LoadReporter::ReportStreamCreated(const grpc::string& hostname, void LoadReporter::ReportStreamClosed(const grpc::string& hostname, const grpc::string& lb_id) { - std::lock_guard lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.ReportStreamClosed(hostname, lb_id); gpr_log(GPR_INFO, "[LR %p] Report stream closed (host: %s, LB ID: %s).", this, hostname.c_str(), lb_id.c_str()); @@ -407,7 +407,7 @@ void LoadReporter::ProcessViewDataCallStart( LoadRecordKey key(client_ip_and_token, user_id); LoadRecordValue value = LoadRecordValue(start_count); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -459,7 +459,7 @@ void LoadReporter::ProcessViewDataCallEnd( LoadRecordValue value = LoadRecordValue( 0, ok_count, error_count, bytes_sent, bytes_received, latency_ms); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } @@ -486,7 +486,7 @@ void LoadReporter::ProcessViewDataOtherCallMetrics( LoadRecordValue value = LoadRecordValue( metric_name, static_cast(num_calls), total_metric_value); { - std::unique_lock lock(store_mu_); + grpc_core::MutexLock lock(&store_mu_); load_data_store_.MergeRow(host, key, value); } } diff --git a/src/cpp/server/load_reporter/load_reporter.h b/src/cpp/server/load_reporter/load_reporter.h index b2254d56016..766e02a407a 100644 --- a/src/cpp/server/load_reporter/load_reporter.h +++ b/src/cpp/server/load_reporter/load_reporter.h @@ -29,6 +29,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/cpp/server/load_reporter/load_data_store.h" #include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h" @@ -212,11 +213,11 @@ class LoadReporter { std::atomic next_lb_id_{0}; const std::chrono::seconds feedback_sample_window_seconds_; - std::mutex feedback_mu_; + grpc_core::Mutex feedback_mu_; std::deque feedback_records_; // TODO(juanlishen): Lock in finer grain. Locking the whole store may be // too expensive. - std::mutex store_mu_; + grpc_core::Mutex store_mu_; LoadDataStore load_data_store_; std::unique_ptr census_view_provider_; std::unique_ptr cpu_stats_provider_; diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc index 859ad9946c8..9eaab5d6366 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc @@ -48,7 +48,7 @@ LoadReporterAsyncServiceImpl::~LoadReporterAsyncServiceImpl() { // We will reach here after the server starts shutting down. shutdown_ = true; { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); cq_->Shutdown(); } if (next_fetch_and_sample_alarm_ != nullptr) @@ -62,7 +62,7 @@ void LoadReporterAsyncServiceImpl::ScheduleNextFetchAndSample() { gpr_time_from_millis(kFetchAndSampleIntervalSeconds * 1000, GPR_TIMESPAN)); { - std::unique_lock lock(cq_shutdown_mu_); + grpc_core::MutexLock lock(&cq_shutdown_mu_); if (shutdown_) return; // TODO(juanlishen): Improve the Alarm implementation to reuse a single // instance for multiple events. @@ -119,7 +119,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::CreateAndStart( std::make_shared(cq, service, load_reporter); ReportLoadHandler* p = handler.get(); { - std::unique_lock lock(service->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service->cq_shutdown_mu_); if (service->shutdown_) return; p->on_done_notified_ = CallableTag(std::bind(&ReportLoadHandler::OnDoneNotified, p, @@ -164,9 +164,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnRequestDelivered( // instance will deallocate itself when it's done. CreateAndStart(cq_, service_, load_reporter_); { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "OnRequestDelivered"); return; } @@ -222,9 +222,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnReadDone( SendReport(self, true /* ok */); // Expect this read to fail. { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "OnReadDone"); return; } @@ -254,9 +254,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::ScheduleNextReport( gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(load_report_interval_ms_, GPR_TIMESPAN)); { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "ScheduleNextReport"); return; } @@ -294,9 +294,9 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::SendReport( call_status_ = INITIAL_RESPONSE_SENT; } { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::ReleasableMutexLock lock(&service_->cq_shutdown_mu_); if (service_->shutdown_) { - lock.release()->unlock(); + lock.Unlock(); Shutdown(std::move(self), "SendReport"); return; } @@ -342,7 +342,7 @@ void LoadReporterAsyncServiceImpl::ReportLoadHandler::Shutdown( // OnRequestDelivered() may be called after OnDoneNotified(), so we need to // try to Finish() every time we are in Shutdown(). if (call_status_ >= DELIVERED && call_status_ < FINISH_CALLED) { - std::unique_lock lock(service_->cq_shutdown_mu_); + grpc_core::MutexLock lock(&service_->cq_shutdown_mu_); if (!service_->shutdown_) { on_finish_done_ = CallableTag(std::bind(&ReportLoadHandler::OnFinishDone, this, diff --git a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h index 6fc577ff493..3087cbfc04d 100644 --- a/src/cpp/server/load_reporter/load_reporter_async_service_impl.h +++ b/src/cpp/server/load_reporter/load_reporter_async_service_impl.h @@ -25,6 +25,7 @@ #include #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/cpp/server/load_reporter/load_reporter.h" @@ -181,7 +182,7 @@ class LoadReporterAsyncServiceImpl std::unique_ptr cq_; // To synchronize the operations related to shutdown state of cq_, so that we // don't enqueue new tags into cq_ after it is already shut down. - std::mutex cq_shutdown_mu_; + grpc_core::Mutex cq_shutdown_mu_; std::atomic_bool shutdown_{false}; std::unique_ptr<::grpc_core::Thread> thread_; std::unique_ptr load_reporter_; diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index ebc4c6e8009..af76ffbe9b5 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -31,18 +31,13 @@ namespace grpc_impl { -class ResourceQuota; -} - -namespace grpc { - -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() @@ -72,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. " @@ -107,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. " @@ -120,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; } @@ -179,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) { @@ -193,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_); @@ -256,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) { @@ -287,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)); } } @@ -308,7 +304,7 @@ 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_, @@ -398,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); } @@ -413,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 aa9fdac9bea..64a6de97d7e 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -388,9 +388,9 @@ class Server::CallbackRequest final : public Server::CallbackRequestBase { // The counter of outstanding requests must be decremented // under a lock in case it causes the server shutdown. - std::lock_guard l(server_->callback_reqs_mu_); + grpc::internal::MutexLock l(&server_->callback_reqs_mu_); if (--server_->callback_reqs_outstanding_ == 0) { - server_->callback_reqs_done_cv_.notify_one(); + server_->callback_reqs_done_cv_.Signal(); } } @@ -814,12 +814,12 @@ Server::Server( Server::~Server() { { - std::unique_lock lock(mu_); + grpc::internal::ReleasableMutexLock lock(&mu_); if (callback_cq_ != nullptr) { callback_cq_->Shutdown(); } if (started_ && !shutdown_) { - lock.unlock(); + lock.Unlock(); Shutdown(); } else if (!started_) { // Shutdown the completion queues @@ -1051,7 +1051,7 @@ void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { } void Server::ShutdownInternal(gpr_timespec deadline) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (shutdown_) { return; } @@ -1102,9 +1102,9 @@ void Server::ShutdownInternal(gpr_timespec deadline) { // will report a failure, indicating a shutdown and again we won't end // up incrementing the counter. { - std::unique_lock cblock(callback_reqs_mu_); - callback_reqs_done_cv_.wait( - cblock, [this] { return callback_reqs_outstanding_ == 0; }); + grpc::internal::MutexLock cblock(&callback_reqs_mu_); + callback_reqs_done_cv_.WaitUntil( + &callback_reqs_mu_, [this] { return callback_reqs_outstanding_ == 0; }); } // Drain the shutdown queue (if the previous call to AsyncNext() timed out @@ -1114,13 +1114,13 @@ void Server::ShutdownInternal(gpr_timespec deadline) { } shutdown_notified_ = true; - shutdown_cv_.notify_all(); + shutdown_cv_.Broadcast(); } void Server::Wait() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); while (started_ && !shutdown_notified_) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } } @@ -1322,7 +1322,7 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { CompletionQueue* Server::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-server CQ registered - std::lock_guard l(mu_); + grpc::internal::MutexLock l(&mu_); if (callback_cq_ == nullptr) { auto* shutdown_callback = new ShutdownCallback; callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{ diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 73fd6a62c48..eced89d1a79 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -33,6 +33,7 @@ #include #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/surface/call.h" namespace grpc { @@ -96,7 +97,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void SetCancelCallback(std::function callback) { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); if (finalized_ && (cancelled_ != 0)) { callback(); @@ -107,7 +108,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { } void ClearCancelCallback() { - std::lock_guard g(mu_); + grpc_core::MutexLock g(&mu_); cancel_callback_ = nullptr; } @@ -144,7 +145,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { private: bool CheckCancelledNoPluck() { - std::lock_guard g(mu_); + grpc_core::MutexLock lock(&mu_); return finalized_ ? (cancelled_ != 0) : false; } @@ -154,7 +155,7 @@ class ServerContext::CompletionOp final : public internal::CallOpSetInterface { void* tag_; void* core_cq_tag_; grpc_core::RefCount refs_; - std::mutex mu_; + grpc_core::Mutex mu_; bool finalized_; int cancelled_; // This is an int (not bool) because it is passed to core std::function cancel_callback_; @@ -186,7 +187,7 @@ void ServerContext::CompletionOp::FillOps(internal::Call* call) { bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) { bool ret = false; - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); if (done_intercepting_) { /* We are done intercepting. */ if (has_tag_) { @@ -209,19 +210,21 @@ 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_(); } - // Release the lock since we are going to be calling a callback and - // interceptors now - lock.unlock(); + // Release the lock since we may call a callback and interceptors now. + lock.Unlock(); if (call_cancel && reactor_ != nullptr) { - reactor_->OnCancel(); + reactor_->MaybeCallOnCancel(); } - /* Add interception point and run through interceptors */ interceptor_methods_.AddInterceptionHookPoint( experimental::InterceptionHookPoints::POST_RECV_CLOSE); diff --git a/src/cpp/thread_manager/thread_manager.cc b/src/cpp/thread_manager/thread_manager.cc index 3e8606a76fd..2b65352f797 100644 --- a/src/cpp/thread_manager/thread_manager.cc +++ b/src/cpp/thread_manager/thread_manager.cc @@ -62,7 +62,7 @@ ThreadManager::ThreadManager(const char* name, ThreadManager::~ThreadManager() { { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); GPR_ASSERT(num_threads_ == 0); } @@ -72,38 +72,38 @@ ThreadManager::~ThreadManager() { } void ThreadManager::Wait() { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); while (num_threads_ != 0) { - shutdown_cv_.wait(lock); + shutdown_cv_.Wait(&mu_); } } void ThreadManager::Shutdown() { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); shutdown_ = true; } bool ThreadManager::IsShutdown() { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); return shutdown_; } int ThreadManager::GetMaxActiveThreadsSoFar() { - std::lock_guard list_lock(list_mu_); + grpc_core::MutexLock list_lock(&list_mu_); return max_active_threads_sofar_; } void ThreadManager::MarkAsCompleted(WorkerThread* thd) { { - std::lock_guard list_lock(list_mu_); + grpc_core::MutexLock list_lock(&list_mu_); completed_threads_.push_back(thd); } { - std::lock_guard lock(mu_); + grpc_core::MutexLock lock(&mu_); num_threads_--; if (num_threads_ == 0) { - shutdown_cv_.notify_one(); + shutdown_cv_.Signal(); } } @@ -116,7 +116,7 @@ void ThreadManager::CleanupCompletedThreads() { { // swap out the completed threads list: allows other threads to clean up // more quickly - std::unique_lock lock(list_mu_); + grpc_core::MutexLock lock(&list_mu_); completed_threads.swap(completed_threads_); } for (auto thd : completed_threads) delete thd; @@ -132,7 +132,7 @@ void ThreadManager::Initialize() { } { - std::unique_lock lock(mu_); + grpc_core::MutexLock lock(&mu_); num_pollers_ = min_pollers_; num_threads_ = min_pollers_; max_active_threads_sofar_ = min_pollers_; @@ -149,7 +149,7 @@ void ThreadManager::MainWorkLoop() { bool ok; WorkStatus work_status = PollForWork(&tag, &ok); - std::unique_lock lock(mu_); + grpc_core::ReleasableMutexLock lock(&mu_); // Reduce the number of pollers by 1 and check what happened with the poll num_pollers_--; bool done = false; @@ -176,30 +176,30 @@ void ThreadManager::MainWorkLoop() { max_active_threads_sofar_ = num_threads_; } // Drop lock before spawning thread to avoid contention - lock.unlock(); + lock.Unlock(); new WorkerThread(this); } else if (num_pollers_ > 0) { // There is still at least some thread polling, so we can go on // even though we are below the number of pollers that we would // like to have (min_pollers_) - lock.unlock(); + lock.Unlock(); } else { // There are no pollers to spare and we couldn't allocate // a new thread, so resources are exhausted! - lock.unlock(); + lock.Unlock(); resource_exhausted = true; } } else { // There are a sufficient number of pollers available so we can do // the work and continue polling with our existing poller threads - lock.unlock(); + lock.Unlock(); } // Lock is always released at this point - do the application work // or return resource exhausted if there is new work but we couldn't // get a thread in which to do it. DoWork(tag, ok, !resource_exhausted); // Take the lock again to check post conditions - lock.lock(); + lock.Lock(); // If we're shutdown, we should finish at this point. if (shutdown_) done = true; break; diff --git a/src/cpp/thread_manager/thread_manager.h b/src/cpp/thread_manager/thread_manager.h index 6f0bd17c5fe..2fbf309d421 100644 --- a/src/cpp/thread_manager/thread_manager.h +++ b/src/cpp/thread_manager/thread_manager.h @@ -26,6 +26,7 @@ #include +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/resource_quota.h" @@ -140,10 +141,10 @@ class ThreadManager { // Protects shutdown_, num_pollers_, num_threads_ and // max_active_threads_sofar_ - std::mutex mu_; + grpc_core::Mutex mu_; bool shutdown_; - std::condition_variable shutdown_cv_; + grpc_core::CondVar shutdown_cv_; // The resource user object to use when requesting quota to create threads // @@ -169,7 +170,7 @@ class ThreadManager { // ever set so far int max_active_threads_sofar_; - std::mutex list_mu_; + grpc_core::Mutex list_mu_; std::list completed_threads_; }; 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/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.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/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/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.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/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/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/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/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_java_oracle8/Dockerfile.include b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include index e80b51778c6..7307e29f0a0 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include +++ b/templates/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile.include @@ -15,13 +15,6 @@ <%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/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/test/core/client_channel/BUILD b/test/core/client_channel/BUILD index 68a71632daf..a9cfa961ec2 100644 --- a/test/core/client_channel/BUILD +++ b/test/core/client_channel/BUILD @@ -79,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 b3c58bf29b4..10b9314a84a 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -385,6 +385,7 @@ def grpc_end2end_tests(): ":proxy", ":local_util", ], + tags = ["no_windows"], ) for f, fopt in END2END_FIXTURES.items(): @@ -398,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) @@ -413,6 +415,7 @@ def grpc_end2end_tests(): t, poller, ], + tags = ["no_windows"], ) def grpc_end2end_nosec_tests(): @@ -435,6 +438,7 @@ def grpc_end2end_nosec_tests(): ":proxy", ":local_util", ], + tags = ["no_windows"], ) for f, fopt in END2END_NOSEC_FIXTURES.items(): @@ -450,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) 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/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/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/util/BUILD b/test/core/util/BUILD index b10d3e4287b..98e69c6ef34 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -133,6 +133,7 @@ grpc_cc_library( ":grpc_test_util", "//:grpc", ], + tags = ["no_windows"], ) grpc_cc_test( diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index 91419cb257b..d326b2ed37e 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -168,24 +169,24 @@ class ClientChannelStressTest { explicit ServerThread(const grpc::string& type, const grpc::string& server_host, T* service) : type_(type), service_(service) { - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Start from firing before the wait below is hit. - std::unique_lock lock(mu); + grpc::internal::MutexLock lock(&mu); port_ = grpc_pick_unused_port_or_die(); gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); - std::condition_variable cond; + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Start(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Start(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // 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); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -193,7 +194,7 @@ class ClientChannelStressTest { InsecureServerCredentials()); builder.RegisterService(service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { 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 77f9db94acc..6623a2ff55f 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -98,7 +99,7 @@ class MyTestServiceImpl : public TestServiceImpl { Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) override { { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } AddClient(context->peer()); @@ -106,29 +107,29 @@ class MyTestServiceImpl : public TestServiceImpl { } int request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; } std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; + grpc::internal::Mutex mu_; int request_count_; - std::mutex clients_mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -293,18 +294,18 @@ class ClientLbEnd2endTest : public ::testing::Test { void Start(const grpc::string& server_host) { gpr_log(GPR_INFO, "starting server on port %d", port_); started_ = true; - std::mutex mu; - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::Mutex mu; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerData::Serve, this, server_host, &mu, &cond))); - cond.wait(lock, [this] { return server_ready_; }); + cond.WaitUntil(&mu, [this] { return server_ready_; }); server_ready_ = false; gpr_log(GPR_INFO, "server startup complete"); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -313,9 +314,9 @@ class ClientLbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), std::move(creds)); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - std::lock_guard lock(*mu); + grpc::internal::MutexLock lock(mu); server_ready_ = true; - cond->notify_one(); + cond->Signal(); } void Shutdown() { @@ -1374,7 +1375,7 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { void TearDown() override { ClientLbEnd2endTest::TearDown(); } int trailers_intercepted() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return trailers_intercepted_; } @@ -1382,11 +1383,11 @@ class ClientLbInterceptTrailingMetadataTest : public ClientLbEnd2endTest { static void ReportTrailerIntercepted(void* arg) { ClientLbInterceptTrailingMetadataTest* self = static_cast(arg); - std::unique_lock lock(self->mu_); + grpc::internal::MutexLock lock(&self->mu_); self->trailers_intercepted_++; } - std::mutex mu_; + grpc::internal::Mutex mu_; int trailers_intercepted_ = 0; }; 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..f8d887dd24d 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -85,32 +86,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } size_t response_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return response_count_; } void IncreaseResponseCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++response_count_; } void IncreaseRequestCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; response_count_ = 0; } protected: - std::mutex mu_; + grpc::internal::Mutex mu_; private: size_t request_count_ = 0; @@ -148,18 +149,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; - std::mutex clients_mu_; + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -208,67 +209,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); + grpc::internal::MutexLock lock(&mu_); + 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); + } - 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(); + { + grpc::internal::MutexLock 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); + } + { + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [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. + grpc::internal::MutexLock 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_.Signal(); } - load_report_ready_ = true; - load_report_cond_.notify_one(); } } done: @@ -277,12 +285,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Start() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); serverlist_done_ = false; load_report_ready_ = false; responses_and_delays_.clear(); @@ -319,17 +327,17 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - std::unique_lock lock(mu_); - load_report_cond_.wait(lock, [this] { return load_report_ready_; }); + grpc::internal::MutexLock lock(&mu_); + load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.notify_all(); + serverlist_cond_.Broadcast(); } } @@ -348,10 +356,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - std::mutex mu_; - std::condition_variable load_report_cond_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar load_report_cond_; bool load_report_ready_ = false; - std::condition_variable serverlist_cond_; + grpc::internal::CondVar serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -542,8 +550,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)); } @@ -615,22 +625,22 @@ class GrpclbEnd2endTest : public ::testing::Test { GPR_ASSERT(!running_); running_ = true; service_.Start(); - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // 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); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -639,7 +649,7 @@ class GrpclbEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { @@ -1359,7 +1369,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 +1389,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 +1404,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 +1529,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 +1558,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 1cbbc703076..048715300ad 100644 --- a/test/cpp/end2end/test_service_impl.cc +++ b/test/cpp/end2end/test_service_impl.cc @@ -589,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: @@ -602,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); } @@ -657,6 +662,7 @@ CallbackTestServiceImpl::RequestStream() { int server_try_cancel_; std::mutex finish_mu_; bool finished_{false}; + bool on_started_done_{false}; }; return new Reactor; @@ -673,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: @@ -691,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); } @@ -753,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; } @@ -764,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: @@ -778,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); } @@ -839,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/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index e30ce0dbcbf..5b8af61ee33 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -188,7 +189,7 @@ class CommonStressTestAsyncServer : public BaseClass { } void TearDown() override { { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); this->TearDownStart(); shutting_down_ = true; cq_->Shutdown(); @@ -229,7 +230,7 @@ class CommonStressTestAsyncServer : public BaseClass { } } void RefreshContext(int i) { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); if (!shutting_down_) { contexts_[i].state = Context::READY; contexts_[i].srv_ctx.reset(new ServerContext); @@ -253,7 +254,7 @@ class CommonStressTestAsyncServer : public BaseClass { ::grpc::testing::EchoTestService::AsyncService service_; std::unique_ptr cq_; bool shutting_down_; - std::mutex mu_; + grpc::internal::Mutex mu_; std::vector server_threads_; }; @@ -341,9 +342,9 @@ class AsyncClientEnd2endTest : public ::testing::Test { } void Wait() { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); while (rpcs_outstanding_ != 0) { - cv_.wait(l); + cv_.Wait(&mu_); } cq_.Shutdown(); @@ -366,7 +367,7 @@ class AsyncClientEnd2endTest : public ::testing::Test { call->response_reader->Finish(&call->response, &call->status, (void*)call); - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); rpcs_outstanding_++; } } @@ -384,20 +385,20 @@ class AsyncClientEnd2endTest : public ::testing::Test { bool notify; { - std::unique_lock l(mu_); + grpc::internal::MutexLock l(&mu_); rpcs_outstanding_--; notify = (rpcs_outstanding_ == 0); } if (notify) { - cv_.notify_all(); + cv_.Signal(); } } } Common common_; CompletionQueue cq_; - std::mutex mu_; - std::condition_variable cv_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar cv_; int rpcs_outstanding_; }; diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 61e759c61b5..ee248239909 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -84,32 +84,32 @@ template class CountedService : public ServiceType { public: size_t request_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return request_count_; } size_t response_count() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); return response_count_; } void IncreaseResponseCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++response_count_; } void IncreaseRequestCount() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); ++request_count_; } void ResetCounters() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); request_count_ = 0; response_count_ = 0; } protected: - std::mutex mu_; + grpc::internal::Mutex mu_; private: size_t request_count_ = 0; @@ -145,18 +145,18 @@ class BackendServiceImpl : public BackendService { void Shutdown() {} std::set clients() { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); return clients_; } private: void AddClient(const grpc::string& client) { - std::unique_lock lock(clients_mu_); + grpc::internal::MutexLock lock(&clients_mu_); clients_.insert(client); } - std::mutex mu_; - std::mutex clients_mu_; + grpc::internal::Mutex mu_; + grpc::internal::Mutex clients_mu_; std::set clients_; }; @@ -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); + { + grpc::internal::MutexLock lock(&mu_); + if (serverlist_done_) goto done; + } { // Balancer shouldn't receive the call credentials metadata. EXPECT_EQ(context->client_metadata().find(g_kCallCredsMdKey), @@ -230,7 +234,7 @@ class BalancerServiceImpl : public BalancerService { } { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays = responses_and_delays_; } for (const auto& response_and_delay : responses_and_delays) { @@ -238,8 +242,8 @@ class BalancerServiceImpl : public BalancerService { response_and_delay.second); } { - std::unique_lock lock(mu_); - serverlist_cond_.wait(lock, [this] { return serverlist_done_; }); + grpc::internal::MutexLock lock(&mu_); + serverlist_cond_.WaitUntil(&mu_, [this] { return serverlist_done_; }); } if (client_load_reporting_interval_seconds_ > 0) { @@ -250,7 +254,7 @@ class BalancerServiceImpl : public BalancerService { 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_); + grpc::internal::MutexLock lock(&mu_); client_stats_.num_calls_started += request.client_stats().num_calls_started(); client_stats_.num_calls_finished += @@ -267,7 +271,7 @@ class BalancerServiceImpl : public BalancerService { drop_token_count.num_calls(); } load_report_ready_ = true; - load_report_cond_.notify_one(); + load_report_cond_.Signal(); } } } @@ -277,12 +281,12 @@ class BalancerServiceImpl : public BalancerService { } void add_response(const LoadBalanceResponse& response, int send_after_ms) { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); } void Shutdown() { - std::unique_lock lock(mu_); + grpc::internal::MutexLock lock(&mu_); NotifyDoneWithServerlistsLocked(); responses_and_delays_.clear(); client_stats_.Reset(); @@ -314,21 +318,21 @@ class BalancerServiceImpl : public BalancerService { } const ClientStats& WaitForLoadReport() { - std::unique_lock lock(mu_); - load_report_cond_.wait(lock, [this] { return load_report_ready_; }); + grpc::internal::MutexLock lock(&mu_); + load_report_cond_.WaitUntil(&mu_, [this] { return load_report_ready_; }); load_report_ready_ = false; return client_stats_; } void NotifyDoneWithServerlists() { - std::lock_guard lock(mu_); + grpc::internal::MutexLock lock(&mu_); NotifyDoneWithServerlistsLocked(); } void NotifyDoneWithServerlistsLocked() { if (!serverlist_done_) { serverlist_done_ = true; - serverlist_cond_.notify_all(); + serverlist_cond_.Broadcast(); } } @@ -347,10 +351,10 @@ class BalancerServiceImpl : public BalancerService { const int client_load_reporting_interval_seconds_; std::vector responses_and_delays_; - std::mutex mu_; - std::condition_variable load_report_cond_; + grpc::internal::Mutex mu_; + grpc::internal::CondVar load_report_cond_; bool load_report_ready_ = false; - std::condition_variable serverlist_cond_; + grpc::internal::CondVar serverlist_cond_; bool serverlist_done_ = false; ClientStats client_stats_; }; @@ -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(); @@ -629,22 +637,22 @@ class XdsEnd2endTest : public ::testing::Test { gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); GPR_ASSERT(!running_); running_ = true; - std::mutex mu; + grpc::internal::Mutex mu; // We need to acquire the lock here in order to prevent the notify_one // by ServerThread::Serve from firing before the wait below is hit. - std::unique_lock lock(mu); - std::condition_variable cond; + grpc::internal::MutexLock lock(&mu); + grpc::internal::CondVar cond; thread_.reset(new std::thread( std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); - cond.wait(lock); + cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } - void Serve(const grpc::string& server_host, std::mutex* mu, - std::condition_variable* cond) { + void Serve(const grpc::string& server_host, grpc::internal::Mutex* mu, + grpc::internal::CondVar* cond) { // 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); + grpc::internal::MutexLock lock(mu); std::ostringstream server_address; server_address << server_host << ":" << port_; ServerBuilder builder; @@ -653,7 +661,7 @@ class XdsEnd2endTest : public ::testing::Test { builder.AddListeningPort(server_address.str(), creds); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); - cond->notify_one(); + cond->Signal(); } void Shutdown() { @@ -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/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/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/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/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/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/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_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile index a2be2f3465b..979c14db3f6 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile @@ -15,45 +15,20 @@ FROM debian:jessie -# 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 a2be2f3465b..979c14db3f6 100644 --- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile +++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile @@ -15,45 +15,20 @@ FROM debian:jessie -# 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/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/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 a56d2df8530..a0a6e952409 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -987,6 +987,7 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ +include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ @@ -1010,6 +1011,7 @@ 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 \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 6bf498307bb..21e5b49440f 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -989,6 +989,7 @@ include/grpcpp/impl/codegen/status.h \ include/grpcpp/impl/codegen/status_code_enum.h \ include/grpcpp/impl/codegen/string_ref.h \ include/grpcpp/impl/codegen/stub_options.h \ +include/grpcpp/impl/codegen/sync.h \ include/grpcpp/impl/codegen/sync_stream.h \ include/grpcpp/impl/codegen/time.h \ include/grpcpp/impl/grpc_library.h \ @@ -1012,6 +1013,7 @@ 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 \ @@ -1084,12 +1086,12 @@ 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/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/http/format_request.h \ src/core/lib/http/httpcli.h \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index e68e758c64e..1817be44bc3 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1166,12 +1166,12 @@ 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/sync.h \ src/core/lib/gprpp/thd.h \ src/core/lib/gprpp/thd_posix.cc \ src/core/lib/gprpp/thd_windows.cc \ 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_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/remote_build/README.md b/tools/remote_build/README.md index bb27dc7072c..2cd5f03daf1 100644 --- a/tools/remote_build/README.md +++ b/tools/remote_build/README.md @@ -31,8 +31,8 @@ bazel --bazelrc=tools/remote_build/manual.bazelrc test --config=asan //test/... Run on Windows MSVC: ``` -# local manual run only for C++ targets (RBE to be supported) -bazel --bazelrc=tools/remote_build/windows.bazelrc test //test/cpp/... +# 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 diff --git a/tools/remote_build/windows.bazelrc b/tools/remote_build/windows.bazelrc index 70575372d02..492489f3613 100644 --- a/tools/remote_build/windows.bazelrc +++ b/tools/remote_build/windows.bazelrc @@ -1,3 +1,49 @@ -# TODO(yfen): Merge with rbe_common.bazelrc and enable Windows RBE +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 71e2b0d2207..29372824822 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -4744,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", @@ -8015,8 +8033,8 @@ "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/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -8063,8 +8081,8 @@ "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/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/profiling/timers.h" ], @@ -9842,6 +9860,7 @@ }, { "deps": [ + "grpc++_internal_hdrs_only", "grpc_codegen" ], "headers": [ @@ -10038,6 +10057,7 @@ "gpr", "gpr_base_headers", "grpc++_codegen_base", + "grpc++_internal_hdrs_only", "grpc_base_headers", "grpc_transport_inproc_headers", "health_proto", @@ -10130,6 +10150,7 @@ "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", @@ -10249,6 +10270,7 @@ "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", @@ -10330,6 +10352,20 @@ "third_party": false, "type": "filegroup" }, + { + "deps": [], + "headers": [ + "include/grpcpp/impl/codegen/sync.h" + ], + "is_filegroup": true, + "language": "c++", + "name": "grpc++_internal_hdrs_only", + "src": [ + "include/grpcpp/impl/codegen/sync.h" + ], + "third_party": false, + "type": "filegroup" + }, { "deps": [], "headers": [ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 74e68d866e2..cfeff6fa838 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -5373,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'], diff --git a/tools/run_tests/sanity/cpp_banned_constructs.sh b/tools/run_tests/sanity/cpp_banned_constructs.sh new file mode 100755 index 00000000000..68240d6f831 --- /dev/null +++ b/tools/run_tests/sanity/cpp_banned_constructs.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# 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. + +set -e + +cd "$(dirname "$0")/../../.." + +# +# Prevent the use of synchronization and threading constructs from std:: since +# the code should be using grpc_core::Mutex, grpc::internal::Mutex, +# grpc_core::Thread, etc. +# + +egrep -Irn \ + 'std::(mutex|condition_variable|lock_guard|unique_lock|thread)' \ + include/grpc include/grpcpp src/core src/cpp | diff - /dev/null + diff --git a/tools/run_tests/sanity/sanity_tests.yaml b/tools/run_tests/sanity/sanity_tests.yaml index 1913edd4257..40686e0f3ab 100644 --- a/tools/run_tests/sanity/sanity_tests.yaml +++ b/tools/run_tests/sanity/sanity_tests.yaml @@ -10,6 +10,7 @@ - script: tools/run_tests/sanity/check_tracer_sanity.py - script: tools/run_tests/sanity/core_banned_functions.py - script: tools/run_tests/sanity/core_untyped_structs.sh +- script: tools/run_tests/sanity/cpp_banned_constructs.sh - script: tools/run_tests/sanity/check_deprecated_grpc++.py - script: tools/run_tests/sanity/check_port_platform.py - script: tools/buildgen/generate_projects.sh -j 3