diff --git a/BUILD b/BUILD index 7b9e92e29fa..62f0e1d2c56 100644 --- a/BUILD +++ b/BUILD @@ -829,14 +829,18 @@ grpc_cc_library( grpc_cc_library( name = "grpc_lb_policy_grpclb", srcs = [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", ], hdrs = [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", ], @@ -853,14 +857,18 @@ grpc_cc_library( grpc_cc_library( name = "grpc_lb_policy_grpclb_secure", srcs = [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", ], hdrs = [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h", ], diff --git a/CMakeLists.txt b/CMakeLists.txt index ae459acc196..f6c5f9e56d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -676,6 +676,7 @@ add_dependencies(buildtests_cxx golden_file_test) add_dependencies(buildtests_cxx grpc_cli) add_dependencies(buildtests_cxx grpc_tool_test) add_dependencies(buildtests_cxx grpclb_api_test) +add_dependencies(buildtests_cxx grpclb_end2end_test) add_dependencies(buildtests_cxx grpclb_test) add_dependencies(buildtests_cxx health_service_end2end_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -1120,8 +1121,10 @@ add_library(grpc src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c src/core/ext/transport/chttp2/client/insecure/channel_create.c src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c + src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c + src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c third_party/nanopb/pb_common.c @@ -1990,8 +1993,10 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c src/core/ext/filters/load_reporting/load_reporting.c src/core/ext/filters/load_reporting/load_reporting_filter.c + src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c + src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c third_party/nanopb/pb_common.c @@ -10746,6 +10751,55 @@ target_link_libraries(grpclb_api_test endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) +add_executable(grpclb_end2end_test + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.h + test/cpp/end2end/grpclb_end2end_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +protobuf_generate_grpc_cpp( + src/proto/grpc/lb/v1/load_balancer.proto +) + +target_include_directories(grpclb_end2end_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_BUILD_INCLUDE_DIR} + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CARES_PLATFORM_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + 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(grpclb_end2end_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_util + grpc_test_util + grpc++ + grpc + gpr_test_util + gpr + ${_gRPC_GFLAGS_LIBRARIES} +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + add_executable(grpclb_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc diff --git a/Makefile b/Makefile index bf3c500c27b..1a8ee553ca3 100644 --- a/Makefile +++ b/Makefile @@ -1154,6 +1154,7 @@ grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test +grpclb_end2end_test: $(BINDIR)/$(CONFIG)/grpclb_end2end_test grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test health_service_end2end_test: $(BINDIR)/$(CONFIG)/health_service_end2end_test http2_client: $(BINDIR)/$(CONFIG)/http2_client @@ -1578,6 +1579,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/grpc_cli \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ + $(BINDIR)/$(CONFIG)/grpclb_end2end_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ $(BINDIR)/$(CONFIG)/health_service_end2end_test \ $(BINDIR)/$(CONFIG)/http2_client \ @@ -1699,6 +1701,7 @@ buildtests_cxx: privatelibs_cxx \ $(BINDIR)/$(CONFIG)/grpc_cli \ $(BINDIR)/$(CONFIG)/grpc_tool_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \ + $(BINDIR)/$(CONFIG)/grpclb_end2end_test \ $(BINDIR)/$(CONFIG)/grpclb_test \ $(BINDIR)/$(CONFIG)/health_service_end2end_test \ $(BINDIR)/$(CONFIG)/http2_client \ @@ -2081,6 +2084,8 @@ test_cxx: buildtests_cxx $(Q) $(BINDIR)/$(CONFIG)/grpc_tool_test || ( echo test grpc_tool_test failed ; exit 1 ) $(E) "[RUN] Testing grpclb_api_test" $(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 ) + $(E) "[RUN] Testing grpclb_end2end_test" + $(Q) $(BINDIR)/$(CONFIG)/grpclb_end2end_test || ( echo test grpclb_end2end_test failed ; exit 1 ) $(E) "[RUN] Testing grpclb_test" $(Q) $(BINDIR)/$(CONFIG)/grpclb_test || ( echo test grpclb_test failed ; exit 1 ) $(E) "[RUN] Testing health_service_end2end_test" @@ -3099,8 +3104,10 @@ LIBGRPC_SRC = \ src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ + src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \ + src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -3938,8 +3945,10 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c \ src/core/ext/filters/load_reporting/load_reporting.c \ src/core/ext/filters/load_reporting/load_reporting_filter.c \ + src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c \ + src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ @@ -8270,8 +8279,8 @@ PUBLIC_HEADERS_C += \ LIBARES_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBARES_SRC)))) -$(LIBARES_OBJS): CPPFLAGS += -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux) $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DHAVE_CONFIG_H -$(LIBARES_OBJS): CFLAGS += -Wno-sign-conversion -Wno-invalid-source-encoding +$(LIBARES_OBJS): CPPFLAGS += -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux) $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,) +$(LIBARES_OBJS): CFLAGS += -Wno-sign-conversion $(if $(subst MINGW32,,$(SYSTEM)),-Wno-invalid-source-encoding,) $(LIBDIR)/$(CONFIG)/libares.a: $(ZLIB_DEP) $(LIBARES_OBJS) $(E) "[AR] Creating $@" @@ -15092,6 +15101,53 @@ endif $(OBJDIR)/$(CONFIG)/test/cpp/grpclb/grpclb_api_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc +GRPCLB_END2END_TEST_SRC = \ + $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ + test/cpp/end2end/grpclb_end2end_test.cc \ + +GRPCLB_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPCLB_END2END_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/grpclb_end2end_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.0.0+. + +$(BINDIR)/$(CONFIG)/grpclb_end2end_test: protobuf_dep_error + +else + +$(BINDIR)/$(CONFIG)/grpclb_end2end_test: $(PROTOBUF_DEP) $(GRPCLB_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(GRPCLB_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpclb_end2end_test + +endif + +endif + +$(OBJDIR)/$(CONFIG)/src/proto/grpc/lb/v1/load_balancer.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/grpclb_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_grpclb_end2end_test: $(GRPCLB_END2END_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(GRPCLB_END2END_TEST_OBJS:.o=.dep) +endif +endif +$(OBJDIR)/$(CONFIG)/test/cpp/end2end/grpclb_end2end_test.o: $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc + + GRPCLB_TEST_SRC = \ $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \ test/cpp/grpclb/grpclb_test.cc \ diff --git a/Rakefile b/Rakefile index cc02aa130ab..7f8d3a2f4ac 100755 --- a/Rakefile +++ b/Rakefile @@ -80,7 +80,7 @@ task 'dlls' do grpc_config = ENV['GRPC_CONFIG'] || 'opt' verbose = ENV['V'] || '0' - env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result" ' + env = 'CPPFLAGS="-D_WIN32_WINNT=0x600 -DUNICODE -D_UNICODE -Wno-unused-variable -Wno-unused-result -DCARES_STATICLIB" ' env += 'LDFLAGS=-static ' env += 'SYSTEM=MINGW32 ' env += 'EMBED_ZLIB=true ' diff --git a/binding.gyp b/binding.gyp index 582c61282f9..c8dd5c1cfdd 100644 --- a/binding.gyp +++ b/binding.gyp @@ -39,15 +39,16 @@ { 'variables': { 'runtime%': 'node', - # UV integration in C core is enabled by default. It can be disabled - # by setting this argument to anything else. - 'grpc_uv%': 'true', # Some Node installations use the system installation of OpenSSL, and on # some systems, the system OpenSSL still does not have ALPN support. This # will let users recompile gRPC to work without ALPN. 'grpc_alpn%': 'true', # Indicates that the library should be built with gcov. - 'grpc_gcov%': 'false' + 'grpc_gcov%': 'false', + # Indicates that the library should be built with compatibility for musl + # libc, so that it can run on Alpine Linux. This is only necessary if not + # building on Alpine Linux + 'grpc_alpine%': 'false' }, 'target_defaults': { 'configurations': { @@ -86,17 +87,11 @@ 'include' ], 'defines': [ - 'GPR_BACKWARDS_COMPATIBILITY_MODE' + 'GPR_BACKWARDS_COMPATIBILITY_MODE', + 'GRPC_ARES=0', + 'GRPC_UV' ], 'conditions': [ - ['grpc_uv=="true"', { - 'defines': [ - 'GRPC_ARES=0', - # Disabling this while bugs are ironed out. Uncomment this to - # re-enable libuv integration in C core. - 'GRPC_UV' - ] - }], ['grpc_gcov=="true"', { 'cflags': [ '-O0', @@ -115,6 +110,11 @@ '-rdynamic', ], }], + ['grpc_alpine=="true"', { + 'defines': [ + 'GPR_MUSL_LIBC_COMPAT' + ] + }], ['OS!="win" and runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' @@ -535,6 +535,10 @@ } ] }, + ] + }], + ['OS == "win"', { + 'targets': [ # Only want to compile zlib under Windows { 'cflags': [ @@ -569,7 +573,6 @@ }] ], 'targets': [ - { 'cflags': [ '-std=c99', @@ -648,7 +651,6 @@ 'type': 'static_library', 'dependencies': [ 'gpr', - 'node_modules/cares/deps/cares/cares.gyp:cares', ], 'sources': [ 'src/core/lib/surface/init.c', @@ -855,8 +857,10 @@ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -940,20 +944,16 @@ "src/node/ext/call_credentials.cc", "src/node/ext/channel.cc", "src/node/ext/channel_credentials.cc", - "src/node/ext/completion_queue_threadpool.cc", - "src/node/ext/completion_queue_uv.cc", + "src/node/ext/completion_queue.cc", "src/node/ext/node_grpc.cc", "src/node/ext/server.cc", "src/node/ext/server_credentials.cc", - "src/node/ext/server_generic.cc", - "src/node/ext/server_uv.cc", "src/node/ext/slice.cc", "src/node/ext/timeval.cc", ], "dependencies": [ "grpc", "gpr", - "node_modules/cares/deps/cares/cares.gyp:cares", ] }, { diff --git a/build.yaml b/build.yaml index 96cccdd848d..b2930602346 100644 --- a/build.yaml +++ b/build.yaml @@ -488,13 +488,17 @@ filegroups: - grpc_base - name: grpc_lb_policy_grpclb headers: + - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h + - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h src: + - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c + - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c plugin: grpc_lb_policy_grpclb @@ -504,13 +508,17 @@ filegroups: - nanopb - name: grpc_lb_policy_grpclb_secure headers: + - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h + - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h src: + - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c + - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c - src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c plugin: grpc_lb_policy_grpclb @@ -3804,6 +3812,20 @@ targets: - grpc_test_util - grpc++ - grpc +- name: grpclb_end2end_test + gtest: true + build: test + language: c++ + src: + - src/proto/grpc/lb/v1/load_balancer.proto + - test/cpp/end2end/grpclb_end2end_test.cc + deps: + - grpc++_test_util + - grpc_test_util + - grpc++ + - grpc + - gpr_test_util + - gpr - name: grpclb_test gtest: false build: test @@ -4490,10 +4512,11 @@ configs: UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1:suppressions=tools/ubsan_suppressions.txt defaults: ares: - CFLAGS: -Wno-sign-conversion -Wno-invalid-source-encoding + CFLAGS: -Wno-sign-conversion $(if $(subst MINGW32,,$(SYSTEM)),-Wno-invalid-source-encoding,) CPPFLAGS: -Ithird_party/cares -Ithird_party/cares/cares $(if $(subst Linux,,$(SYSTEM)),,-Ithird_party/cares/config_linux) $(if $(subst Darwin,,$(SYSTEM)),,-Ithird_party/cares/config_darwin) -fvisibility=hidden - -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DHAVE_CONFIG_H + -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN -D_HAS_EXCEPTIONS=0 -DNOMINMAX $(if $(subst + MINGW32,,$(SYSTEM)),-DHAVE_CONFIG_H,) benchmark: CPPFLAGS: -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX boringssl: @@ -4539,13 +4562,10 @@ node_modules: - src/node/ext/call_credentials.cc - src/node/ext/channel.cc - src/node/ext/channel_credentials.cc - - src/node/ext/completion_queue_threadpool.cc - - src/node/ext/completion_queue_uv.cc + - src/node/ext/completion_queue.cc - src/node/ext/node_grpc.cc - src/node/ext/server.cc - src/node/ext/server_credentials.cc - - src/node/ext/server_generic.cc - - src/node/ext/server_uv.cc - src/node/ext/slice.cc - src/node/ext/timeval.cc openssl_fallback: diff --git a/config.m4 b/config.m4 index bbd667c9ec4..1c0c6d92fc4 100644 --- a/config.m4 +++ b/config.m4 @@ -291,8 +291,10 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c \ src/core/ext/transport/chttp2/client/insecure/channel_create.c \ src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c \ + src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \ + src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ third_party/nanopb/pb_common.c \ diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 07755ac7279..241eba01dd2 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -434,8 +434,10 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/uri_parser.h', 'src/core/ext/filters/deadline/deadline_filter.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', @@ -668,8 +670,10 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', @@ -895,8 +899,10 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/uri_parser.h', 'src/core/ext/filters/deadline/deadline_filter.h', 'src/core/ext/transport/chttp2/client/chttp2_connector.h', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h', 'third_party/nanopb/pb.h', diff --git a/grpc.gemspec b/grpc.gemspec index 1cd6d66335e..b96f3cbab54 100755 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -350,8 +350,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/uri_parser.h ) s.files += %w( src/core/ext/filters/deadline/deadline_filter.h ) s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h ) + s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h ) + s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h ) s.files += %w( third_party/nanopb/pb.h ) @@ -584,8 +586,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.c ) s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c ) + s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c ) + s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c ) s.files += %w( third_party/nanopb/pb_common.c ) diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h index f334ba61d6c..9fe2bbb75e7 100644 --- a/include/grpc++/impl/codegen/call.h +++ b/include/grpc++/impl/codegen/call.h @@ -364,28 +364,6 @@ class CallOpRecvMessage { bool allow_not_getting_message_; }; -namespace CallOpGenericRecvMessageHelper { -class DeserializeFunc { - public: - virtual Status Deserialize(grpc_byte_buffer* buf) = 0; - virtual ~DeserializeFunc() {} -}; - -template -class DeserializeFuncType final : public DeserializeFunc { - public: - DeserializeFuncType(R* message) : message_(message) {} - Status Deserialize(grpc_byte_buffer* buf) override { - return SerializationTraits::Deserialize(buf, message_); - } - - ~DeserializeFuncType() override {} - - private: - R* message_; // Not a managed pointer because management is external to this -}; -} // namespace CallOpGenericRecvMessageHelper - class CallOpGenericRecvMessage { public: CallOpGenericRecvMessage() @@ -393,11 +371,9 @@ class CallOpGenericRecvMessage { template void RecvMessage(R* message) { - // Use an explicit base class pointer to avoid resolution error in the - // following unique_ptr::reset for some old implementations. - CallOpGenericRecvMessageHelper::DeserializeFunc* func = - new CallOpGenericRecvMessageHelper::DeserializeFuncType(message); - deserialize_.reset(func); + deserialize_ = [message](grpc_byte_buffer* buf) -> Status { + return SerializationTraits::Deserialize(buf, message); + }; } // Do not change status if no message is received. @@ -420,7 +396,7 @@ class CallOpGenericRecvMessage { if (recv_buf_) { if (*status) { got_message = true; - *status = deserialize_->Deserialize(recv_buf_).ok(); + *status = deserialize_(recv_buf_).ok(); } else { got_message = false; g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_); @@ -431,11 +407,12 @@ class CallOpGenericRecvMessage { *status = false; } } - deserialize_.reset(); + deserialize_ = DeserializeFunc(); } private: - std::unique_ptr deserialize_; + typedef std::function DeserializeFunc; + DeserializeFunc deserialize_; grpc_byte_buffer* recv_buf_; bool allow_not_getting_message_; }; diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index b2c38b2c924..4738e02ecba 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -293,6 +293,9 @@ each time recvmsg (or equivalent) is called */ "grpc.experimental.tcp_min_read_chunk_size" #define GRPC_ARG_TCP_MAX_READ_CHUNK_SIZE \ "grpc.experimental.tcp_max_read_chunk_size" +/* Timeout in milliseconds to use for calls to the grpclb load balancer. + If 0 or unset, the balancer calls will have no deadline. */ +#define GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS "grpc.grpclb_timeout_ms" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index e12f6f4e998..14e348fadb2 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -189,7 +189,7 @@ #ifdef __GLIBC__ #define GPR_POSIX_CRASH_HANDLER 1 #else /* musl libc */ -#define GRPC_MSG_IOVLEN_TYPE int +#define GPR_MUSL_LIBC_COMPAT 1 #endif #elif defined(__APPLE__) #include diff --git a/package.json b/package.json index 6a01ae23243..e1499a089cd 100644 --- a/package.json +++ b/package.json @@ -34,8 +34,7 @@ "lodash": "^4.15.0", "nan": "^2.0.0", "node-pre-gyp": "^0.6.0", - "protobufjs": "^6.7.0", - "cares": "^1.1.5" + "protobufjs": "^6.7.0" }, "devDependencies": { "async": "^2.0.1", diff --git a/package.xml b/package.xml index e7d67eca180..d47708efa4e 100644 --- a/package.xml +++ b/package.xml @@ -359,8 +359,10 @@ + + @@ -593,8 +595,10 @@ + + diff --git a/setup.py b/setup.py index 4cbd1a45a90..18ba802fb0f 100644 --- a/setup.py +++ b/setup.py @@ -144,6 +144,8 @@ CYTHON_EXTENSION_MODULE_NAMES = ('grpc._cython.cygrpc',) CYTHON_HELPER_C_FILES = () CORE_C_FILES = tuple(grpc_core_dependencies.CORE_SOURCE_FILES) +if "win32" in sys.platform and "64bit" in platform.architecture()[0]: + CORE_C_FILES = filter(lambda x: 'third_party/cares' not in x, CORE_C_FILES) EXTENSION_INCLUDE_DIRECTORIES = ( (PYTHON_STEM,) + CORE_INCLUDE + BORINGSSL_INCLUDE + ZLIB_INCLUDE + @@ -163,7 +165,9 @@ DEFINE_MACROS = ( if "win32" in sys.platform: DEFINE_MACROS += (('WIN32_LEAN_AND_MEAN', 1), ('CARES_STATICLIB', 1),) if '64bit' in platform.architecture()[0]: - DEFINE_MACROS += (('MS_WIN64', 1),) + # TODO(zyc): Re-enble c-ares on x64 windows after fixing the + # ares_library_init compilation issue + DEFINE_MACROS += (('MS_WIN64', 1), ('GRPC_ARES', 0),) elif sys.version_info >= (3, 5): # For some reason, this is needed to get access to inet_pton/inet_ntop # on msvc, but only for 32 bits diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index d3e71625d65..a1a0258c680 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -804,6 +804,12 @@ void PrintHeaderService(grpc_generator::Printer *printer, " public:\n"); printer->Indent(); + // Service metadata + printer->Print(*vars, + "static constexpr char const* service_full_name() {\n" + " return \"$Package$$Service$\";\n" + "}\n"); + // Client side printer->Print( "class StubInterface {\n" diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 50ee54abffe..278e5072b26 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -622,9 +622,17 @@ bool PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) { for (StringPairSet::iterator it = imports_set.begin(); it != imports_set.end(); ++it) { - var["ModuleName"] = std::get<0>(*it); + auto module_name = std::get<0>(*it); var["ModuleAlias"] = std::get<1>(*it); - out->Print(var, "import $ModuleName$ as $ModuleAlias$\n"); + const size_t last_dot_pos = module_name.rfind('.'); + if (last_dot_pos == grpc::string::npos) { + var["ImportStatement"] = "import " + module_name; + } else { + var["ImportStatement"] = "from " + module_name.substr(0, last_dot_pos) + + " import " + + module_name.substr(last_dot_pos + 1); + } + out->Print(var, "$ImportStatement$ as $ModuleAlias$\n"); } } return true; diff --git a/src/core/ext/filters/client_channel/client_channel.c b/src/core/ext/filters/client_channel/client_channel.c index 0463b25412a..24843d52e9f 100644 --- a/src/core/ext/filters/client_channel/client_channel.c +++ b/src/core/ext/filters/client_channel/client_channel.c @@ -760,12 +760,6 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx, #define CANCELLED_CALL ((grpc_subchannel_call *)1) -typedef enum { - /* zero so that it can be default-initialized */ - GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING = 0, - GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL -} subchannel_creation_phase; - /** Call data. Holds a pointer to grpc_subchannel_call and the associated machinery to create such a pointer. Handles queueing of stream ops until a call object is ready, waiting @@ -793,8 +787,9 @@ typedef struct client_channel_call_data { gpr_atm subchannel_call; gpr_arena *arena; - subchannel_creation_phase creation_phase; + bool pick_pending; grpc_connected_subchannel *connected_subchannel; + grpc_call_context_element subchannel_call_context[GRPC_CONTEXT_COUNT]; grpc_polling_entity *pollent; grpc_transport_stream_op_batch **waiting_ops; @@ -914,11 +909,10 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_call_element *elem = arg; call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; - GPR_ASSERT(calld->creation_phase == - GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL); + GPR_ASSERT(calld->pick_pending); + calld->pick_pending = false; grpc_polling_entity_del_from_pollset_set(exec_ctx, calld->pollent, chand->interested_parties); - calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; if (calld->connected_subchannel == NULL) { gpr_atm_no_barrier_store(&calld->subchannel_call, 1); fail_locked(exec_ctx, calld, @@ -944,7 +938,8 @@ static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg, .path = calld->path, .start_time = calld->call_start_time, .deadline = calld->deadline, - .arena = calld->arena}; + .arena = calld->arena, + .context = calld->subchannel_call_context}; grpc_error *new_error = grpc_connected_subchannel_create_call( exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call); gpr_atm_rel_store(&calld->subchannel_call, @@ -973,6 +968,7 @@ typedef struct { grpc_metadata_batch *initial_metadata; uint32_t initial_metadata_flags; grpc_connected_subchannel **connected_subchannel; + grpc_call_context_element *subchannel_call_context; grpc_closure *on_ready; grpc_call_element *elem; grpc_closure closure; @@ -984,8 +980,8 @@ typedef struct { static bool pick_subchannel_locked( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, - grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready, - grpc_error *error); + grpc_connected_subchannel **connected_subchannel, + grpc_call_context_element *subchannel_call_context, grpc_closure *on_ready); static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { @@ -997,49 +993,49 @@ static void continue_picking_locked(grpc_exec_ctx *exec_ctx, void *arg, } else { if (pick_subchannel_locked(exec_ctx, cpa->elem, cpa->initial_metadata, cpa->initial_metadata_flags, - cpa->connected_subchannel, cpa->on_ready, - GRPC_ERROR_NONE)) { + cpa->connected_subchannel, + cpa->subchannel_call_context, cpa->on_ready)) { grpc_closure_sched(exec_ctx, cpa->on_ready, GRPC_ERROR_NONE); } } gpr_free(cpa); } +static void cancel_pick_locked(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_error *error) { + channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; + if (chand->lb_policy != NULL) { + grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy, + &calld->connected_subchannel, + GRPC_ERROR_REF(error)); + } + for (grpc_closure *closure = chand->waiting_for_config_closures.head; + closure != NULL; closure = closure->next_data.next) { + continue_picking_args *cpa = closure->cb_arg; + if (cpa->connected_subchannel == &calld->connected_subchannel) { + cpa->connected_subchannel = NULL; + grpc_closure_sched(exec_ctx, cpa->on_ready, + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Pick cancelled", &error, 1)); + } + } + GRPC_ERROR_UNREF(error); +} + static bool pick_subchannel_locked( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_metadata_batch *initial_metadata, uint32_t initial_metadata_flags, - grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready, - grpc_error *error) { + grpc_connected_subchannel **connected_subchannel, + grpc_call_context_element *subchannel_call_context, + grpc_closure *on_ready) { GPR_TIMER_BEGIN("pick_subchannel", 0); channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; - continue_picking_args *cpa; - grpc_closure *closure; GPR_ASSERT(connected_subchannel); - if (initial_metadata == NULL) { - if (chand->lb_policy != NULL) { - grpc_lb_policy_cancel_pick_locked(exec_ctx, chand->lb_policy, - connected_subchannel, - GRPC_ERROR_REF(error)); - } - for (closure = chand->waiting_for_config_closures.head; closure != NULL; - closure = closure->next_data.next) { - cpa = closure->cb_arg; - if (cpa->connected_subchannel == connected_subchannel) { - cpa->connected_subchannel = NULL; - grpc_closure_sched(exec_ctx, cpa->on_ready, - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Pick cancelled", &error, 1)); - } - } - GPR_TIMER_END("pick_subchannel", 0); - GRPC_ERROR_UNREF(error); - return true; - } - GPR_ASSERT(error == GRPC_ERROR_NONE); if (chand->lb_policy != NULL) { apply_final_configuration_locked(exec_ctx, elem); grpc_lb_policy *lb_policy = chand->lb_policy; @@ -1062,8 +1058,7 @@ static bool pick_subchannel_locked( } } const grpc_lb_policy_pick_args inputs = { - initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem, - gpr_inf_future(GPR_CLOCK_MONOTONIC)}; + initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem}; // Wrap the user-provided callback in order to hold a strong reference to // the LB policy for the duration of the pick. @@ -1076,8 +1071,8 @@ static bool pick_subchannel_locked( GRPC_LB_POLICY_REF(lb_policy, "pick_subchannel_wrapping"); w_on_pick_arg->lb_policy = lb_policy; const bool pick_done = grpc_lb_policy_pick_locked( - exec_ctx, lb_policy, &inputs, connected_subchannel, NULL, - &w_on_pick_arg->wrapper_closure); + exec_ctx, lb_policy, &inputs, connected_subchannel, + subchannel_call_context, NULL, &w_on_pick_arg->wrapper_closure); if (pick_done) { /* synchronous grpc_lb_policy_pick call. Unref the LB policy. */ GRPC_LB_POLICY_UNREF(exec_ctx, w_on_pick_arg->lb_policy, @@ -1096,10 +1091,11 @@ static bool pick_subchannel_locked( &chand->on_resolver_result_changed); } if (chand->resolver != NULL) { - cpa = gpr_malloc(sizeof(*cpa)); + continue_picking_args *cpa = gpr_malloc(sizeof(*cpa)); cpa->initial_metadata = initial_metadata; cpa->initial_metadata_flags = initial_metadata_flags; cpa->connected_subchannel = connected_subchannel; + cpa->subchannel_call_context = subchannel_call_context; cpa->on_ready = on_ready; cpa->elem = elem; grpc_closure_init(&cpa->closure, continue_picking_locked, cpa, @@ -1151,16 +1147,13 @@ static void start_transport_stream_op_batch_locked_inner( error to the caller when the first op does get passed down. */ calld->cancel_error = GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error); - switch (calld->creation_phase) { - case GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING: - fail_locked(exec_ctx, calld, - GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); - break; - case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL: - pick_subchannel_locked( - exec_ctx, elem, NULL, 0, &calld->connected_subchannel, NULL, - GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); - break; + if (calld->pick_pending) { + cancel_pick_locked( + exec_ctx, elem, + GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); + } else { + fail_locked(exec_ctx, calld, + GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); } grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, @@ -1170,9 +1163,9 @@ static void start_transport_stream_op_batch_locked_inner( } } /* if we don't have a subchannel, try to get one */ - if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && - calld->connected_subchannel == NULL && op->send_initial_metadata) { - calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL; + if (!calld->pick_pending && calld->connected_subchannel == NULL && + op->send_initial_metadata) { + calld->pick_pending = true; grpc_closure_init(&calld->next_step, subchannel_ready_locked, elem, grpc_combiner_scheduler(chand->combiner, true)); GRPC_CALL_STACK_REF(calld->owning_call, "pick_subchannel"); @@ -1183,8 +1176,9 @@ static void start_transport_stream_op_batch_locked_inner( exec_ctx, elem, op->payload->send_initial_metadata.send_initial_metadata, op->payload->send_initial_metadata.send_initial_metadata_flags, - &calld->connected_subchannel, &calld->next_step, GRPC_ERROR_NONE)) { - calld->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING; + &calld->connected_subchannel, calld->subchannel_call_context, + &calld->next_step)) { + calld->pick_pending = false; GRPC_CALL_STACK_UNREF(exec_ctx, calld->owning_call, "pick_subchannel"); } else { grpc_polling_entity_add_to_pollset_set(exec_ctx, calld->pollent, @@ -1192,15 +1186,15 @@ static void start_transport_stream_op_batch_locked_inner( } } /* if we've got a subchannel, then let's ask it to create a call */ - if (calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING && - calld->connected_subchannel != NULL) { + if (!calld->pick_pending && calld->connected_subchannel != NULL) { grpc_subchannel_call *subchannel_call = NULL; const grpc_connected_subchannel_call_args call_args = { .pollent = calld->pollent, .path = calld->path, .start_time = calld->call_start_time, .deadline = calld->deadline, - .arena = calld->arena}; + .arena = calld->arena, + .context = calld->subchannel_call_context}; grpc_error *error = grpc_connected_subchannel_create_call( exec_ctx, calld->connected_subchannel, &call_args, &subchannel_call); gpr_atm_rel_store(&calld->subchannel_call, @@ -1349,12 +1343,18 @@ static void cc_destroy_call_elem(grpc_exec_ctx *exec_ctx, then_schedule_closure = NULL; GRPC_SUBCHANNEL_CALL_UNREF(exec_ctx, call, "client_channel_destroy_call"); } - GPR_ASSERT(calld->creation_phase == GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING); + GPR_ASSERT(!calld->pick_pending); GPR_ASSERT(calld->waiting_ops_count == 0); if (calld->connected_subchannel != NULL) { GRPC_CONNECTED_SUBCHANNEL_UNREF(exec_ctx, calld->connected_subchannel, "picked"); } + for (size_t i = 0; i < GRPC_CONTEXT_COUNT; ++i) { + if (calld->subchannel_call_context[i].value != NULL) { + calld->subchannel_call_context[i].destroy( + calld->subchannel_call_context[i].value); + } + } gpr_free(calld->waiting_ops); grpc_closure_sched(exec_ctx, then_schedule_closure, GRPC_ERROR_NONE); } @@ -1450,12 +1450,12 @@ static void watch_connectivity_state_locked(grpc_exec_ctx *exec_ctx, void *arg, void grpc_client_channel_watch_connectivity_state( grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_pollset *pollset, - grpc_connectivity_state *state, grpc_closure *on_complete) { + grpc_connectivity_state *state, grpc_closure *closure) { channel_data *chand = elem->channel_data; external_connectivity_watcher *w = gpr_malloc(sizeof(*w)); w->chand = chand; w->pollset = pollset; - w->on_complete = on_complete; + w->on_complete = closure; w->state = state; grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties, pollset); GRPC_CHANNEL_STACK_REF(w->chand->owning_stack, diff --git a/src/core/ext/filters/client_channel/lb_policy.c b/src/core/ext/filters/client_channel/lb_policy.c index 2d31499d13e..112ba406581 100644 --- a/src/core/ext/filters/client_channel/lb_policy.c +++ b/src/core/ext/filters/client_channel/lb_policy.c @@ -119,9 +119,10 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx, int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, + grpc_call_context_element *context, void **user_data, grpc_closure *on_complete) { return policy->vtable->pick_locked(exec_ctx, policy, pick_args, target, - user_data, on_complete); + context, user_data, on_complete); } void grpc_lb_policy_cancel_pick_locked(grpc_exec_ctx *exec_ctx, diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index 25427666ae7..184b2ef720c 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -43,9 +43,6 @@ typedef struct grpc_lb_policy grpc_lb_policy; typedef struct grpc_lb_policy_vtable grpc_lb_policy_vtable; -typedef void (*grpc_lb_completion)(void *cb_arg, grpc_subchannel *subchannel, - grpc_status_code status, const char *errmsg); - struct grpc_lb_policy { const grpc_lb_policy_vtable *vtable; gpr_atm ref_pair; @@ -65,8 +62,6 @@ typedef struct grpc_lb_policy_pick_args { uint32_t initial_metadata_flags; /** Storage for LB token in \a initial_metadata, or NULL if not used */ grpc_linked_mdelem *lb_token_mdelem_storage; - /** Deadline for the call to the LB server */ - gpr_timespec deadline; } grpc_lb_policy_pick_args; struct grpc_lb_policy_vtable { @@ -76,7 +71,8 @@ struct grpc_lb_policy_vtable { /** \see grpc_lb_policy_pick */ int (*pick_locked)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, void **user_data, + grpc_connected_subchannel **target, + grpc_call_context_element *context, void **user_data, grpc_closure *on_complete); /** \see grpc_lb_policy_cancel_pick */ @@ -156,6 +152,8 @@ void grpc_lb_policy_init(grpc_lb_policy *policy, \a target will be set to the selected subchannel, or NULL on failure. Upon success, \a user_data will be set to whatever opaque information may need to be propagated from the LB policy, or NULL if not needed. + \a context will be populated with context to pass to the subchannel + call, if needed. If the pick succeeds and a result is known immediately, a non-zero value will be returned. Otherwise, \a on_complete will be invoked @@ -167,6 +165,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy, int grpc_lb_policy_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, + grpc_call_context_element *context, void **user_data, grpc_closure *on_complete); /** Perform a connected subchannel ping (see \a grpc_connected_subchannel_ping) diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c new file mode 100644 index 00000000000..67baa46de71 --- /dev/null +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c @@ -0,0 +1,153 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h" + +#include +#include + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/profiling/timers.h" + +static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem, + grpc_channel_element_args *args) { + return GRPC_ERROR_NONE; +} + +static void destroy_channel_elem(grpc_exec_ctx *exec_ctx, + grpc_channel_element *elem) {} + +typedef struct { + // Stats object to update. + grpc_grpclb_client_stats *client_stats; + // State for intercepting send_initial_metadata. + grpc_closure on_complete_for_send; + grpc_closure *original_on_complete_for_send; + bool send_initial_metadata_succeeded; + // State for intercepting recv_initial_metadata. + grpc_closure recv_initial_metadata_ready; + grpc_closure *original_recv_initial_metadata_ready; + bool recv_initial_metadata_succeeded; +} call_data; + +static void on_complete_for_send(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + call_data *calld = arg; + if (error == GRPC_ERROR_NONE) { + calld->send_initial_metadata_succeeded = true; + } + grpc_closure_run(exec_ctx, calld->original_on_complete_for_send, + GRPC_ERROR_REF(error)); +} + +static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + call_data *calld = arg; + if (error == GRPC_ERROR_NONE) { + calld->recv_initial_metadata_succeeded = true; + } + grpc_closure_run(exec_ctx, calld->original_recv_initial_metadata_ready, + GRPC_ERROR_REF(error)); +} + +static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, + grpc_call_element *elem, + const grpc_call_element_args *args) { + call_data *calld = elem->call_data; + // Get stats object from context and take a ref. + GPR_ASSERT(args->context != NULL); + GPR_ASSERT(args->context[GRPC_GRPCLB_CLIENT_STATS].value != NULL); + calld->client_stats = grpc_grpclb_client_stats_ref( + args->context[GRPC_GRPCLB_CLIENT_STATS].value); + // Record call started. + grpc_grpclb_client_stats_add_call_started(calld->client_stats); + return GRPC_ERROR_NONE; +} + +static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + const grpc_call_final_info *final_info, + grpc_closure *ignored) { + call_data *calld = elem->call_data; + // Record call finished, optionally setting client_failed_to_send and + // received. + grpc_grpclb_client_stats_add_call_finished( + false /* drop_for_rate_limiting */, false /* drop_for_load_balancing */, + !calld->send_initial_metadata_succeeded /* client_failed_to_send */, + calld->recv_initial_metadata_succeeded /* known_received */, + calld->client_stats); + // All done, so unref the stats object. + grpc_grpclb_client_stats_unref(calld->client_stats); +} + +static void start_transport_stream_op_batch( + grpc_exec_ctx *exec_ctx, grpc_call_element *elem, + grpc_transport_stream_op_batch *batch) { + call_data *calld = elem->call_data; + GPR_TIMER_BEGIN("clr_start_transport_stream_op_batch", 0); + // Intercept send_initial_metadata. + if (batch->send_initial_metadata) { + calld->original_on_complete_for_send = batch->on_complete; + grpc_closure_init(&calld->on_complete_for_send, on_complete_for_send, calld, + grpc_schedule_on_exec_ctx); + batch->on_complete = &calld->on_complete_for_send; + } + // Intercept recv_initial_metadata. + if (batch->recv_initial_metadata) { + calld->original_recv_initial_metadata_ready = + batch->payload->recv_initial_metadata.recv_initial_metadata_ready; + grpc_closure_init(&calld->recv_initial_metadata_ready, + recv_initial_metadata_ready, calld, + grpc_schedule_on_exec_ctx); + batch->payload->recv_initial_metadata.recv_initial_metadata_ready = + &calld->recv_initial_metadata_ready; + } + // Chain to next filter. + grpc_call_next_op(exec_ctx, elem, batch); + GPR_TIMER_END("clr_start_transport_stream_op_batch", 0); +} + +const grpc_channel_filter grpc_client_load_reporting_filter = { + start_transport_stream_op_batch, + grpc_channel_next_op, + sizeof(call_data), + init_call_elem, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + destroy_call_elem, + 0, // sizeof(channel_data) + init_channel_elem, + destroy_channel_elem, + grpc_call_next_get_peer, + grpc_channel_next_get_info, + "client_load_reporting"}; diff --git a/src/node/ext/server_generic.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h similarity index 56% rename from src/node/ext/server_generic.cc rename to src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h index 088273d527c..28b313d8740 100644 --- a/src/node/ext/server_generic.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h @@ -31,45 +31,12 @@ * */ -#ifndef GRPC_UV +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_CLIENT_LOAD_REPORTING_FILTER_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_CLIENT_LOAD_REPORTING_FILTER_H -#include "server.h" +#include "src/core/lib/channel/channel_stack.h" -#include -#include -#include "grpc/grpc.h" -#include "grpc/support/time.h" +extern const grpc_channel_filter grpc_client_load_reporting_filter; -namespace grpc { -namespace node { - -Server::Server(grpc_server *server) : wrapped_server(server) { - grpc_completion_queue_attributes attrs = { - GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_NON_LISTENING}; - shutdown_queue = grpc_completion_queue_create( - grpc_completion_queue_factory_lookup(&attrs), &attrs, NULL); - grpc_server_register_completion_queue(server, shutdown_queue, NULL); -} - -Server::~Server() { - this->ShutdownServer(); - grpc_completion_queue_shutdown(this->shutdown_queue); - grpc_completion_queue_destroy(this->shutdown_queue); -} - -void Server::ShutdownServer() { - if (this->wrapped_server != NULL) { - grpc_server_shutdown_and_notify(this->wrapped_server, this->shutdown_queue, - NULL); - grpc_server_cancel_all_calls(this->wrapped_server); - grpc_completion_queue_pluck(this->shutdown_queue, NULL, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - grpc_server_destroy(this->wrapped_server); - this->wrapped_server = NULL; - } -} - -} // namespace grpc -} // namespace node - -#endif /* GRPC_UV */ +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_CLIENT_LOAD_REPORTING_FILTER_H \ + */ diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c index ad5f0685ec3..695be4fdf27 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c @@ -95,8 +95,7 @@ headers. Therefore, sockaddr.h must always be included first */ #include "src/core/lib/iomgr/sockaddr.h" -#include - +#include #include #include @@ -108,13 +107,16 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/client_channel_factory.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/sockaddr_utils.h" @@ -126,6 +128,7 @@ #include "src/core/lib/support/string.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" +#include "src/core/lib/surface/channel_init.h" #include "src/core/lib/transport/static_metadata.h" #define GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS 20 @@ -147,6 +150,10 @@ static grpc_error *initial_metadata_add_lb_token( lb_token_mdelem_storage, lb_token); } +static void destroy_client_stats(void *arg) { + grpc_grpclb_client_stats_unref(arg); +} + typedef struct wrapped_rr_closure_arg { /* the closure instance using this struct as argument */ grpc_closure wrapper_closure; @@ -163,6 +170,13 @@ typedef struct wrapped_rr_closure_arg { * initial metadata */ grpc_connected_subchannel **target; + /* the context to be populated for the subchannel call */ + grpc_call_context_element *context; + + /* Stats for client-side load reporting. Note that this holds a + * reference, which must be either passed on via context or unreffed. */ + grpc_grpclb_client_stats *client_stats; + /* the LB token associated with the pick */ grpc_mdelem lb_token; @@ -202,6 +216,12 @@ static void wrapped_rr_closure(grpc_exec_ctx *exec_ctx, void *arg, (void *)*wc_arg->target, (void *)wc_arg->rr_policy); abort(); } + // Pass on client stats via context. Passes ownership of the reference. + GPR_ASSERT(wc_arg->client_stats != NULL); + wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats; + wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats; + } else { + grpc_grpclb_client_stats_unref(wc_arg->client_stats); } if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Unreffing RR %p", (void *)wc_arg->rr_policy); @@ -237,6 +257,7 @@ typedef struct pending_pick { static void add_pending_pick(pending_pick **root, const grpc_lb_policy_pick_args *pick_args, grpc_connected_subchannel **target, + grpc_call_context_element *context, grpc_closure *on_complete) { pending_pick *pp = gpr_zalloc(sizeof(*pp)); pp->next = *root; @@ -244,6 +265,7 @@ static void add_pending_pick(pending_pick **root, pp->target = target; pp->wrapped_on_complete_arg.wrapped_closure = on_complete; pp->wrapped_on_complete_arg.target = target; + pp->wrapped_on_complete_arg.context = context; pp->wrapped_on_complete_arg.initial_metadata = pick_args->initial_metadata; pp->wrapped_on_complete_arg.lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; @@ -287,8 +309,8 @@ typedef struct glb_lb_policy { grpc_client_channel_factory *cc_factory; grpc_channel_args *args; - /** deadline for the LB's call */ - gpr_timespec deadline; + /** timeout in milliseconds for the LB call. 0 means no deadline. */ + int lb_call_timeout_ms; /** for communicating with the LB server */ grpc_channel *lb_channel; @@ -316,6 +338,10 @@ typedef struct glb_lb_policy { /************************************************************/ /* client data associated with the LB server communication */ /************************************************************/ + + /* Finished sending initial request. */ + grpc_closure lb_on_sent_initial_request; + /* Status from the LB server has been received. This signals the end of the LB * call. */ grpc_closure lb_on_server_status_received; @@ -348,6 +374,23 @@ typedef struct glb_lb_policy { /** LB call retry timer */ grpc_timer lb_call_retry_timer; + + bool initial_request_sent; + bool seen_initial_response; + + /* Stats for client-side load reporting. Should be unreffed and + * recreated whenever lb_call is replaced. */ + grpc_grpclb_client_stats *client_stats; + /* Interval and timer for next client load report. */ + gpr_timespec client_stats_report_interval; + grpc_timer client_load_report_timer; + bool client_load_report_timer_pending; + bool last_client_load_report_counters_were_zero; + /* Closure used for either the load report timer or the callback for + * completion of sending the load report. */ + grpc_closure client_load_report_closure; + /* Client load report message payload. */ + grpc_byte_buffer *client_load_report_payload; } glb_lb_policy; /* Keeps track and reacts to changes in connectivity of the RR instance */ @@ -552,8 +595,8 @@ static bool pick_from_internal_rr_locked( grpc_connected_subchannel **target, wrapped_rr_closure_arg *wc_arg) { GPR_ASSERT(rr_policy != NULL); const bool pick_done = grpc_lb_policy_pick_locked( - exec_ctx, rr_policy, pick_args, target, (void **)&wc_arg->lb_token, - &wc_arg->wrapper_closure); + exec_ctx, rr_policy, pick_args, target, wc_arg->context, + (void **)&wc_arg->lb_token, &wc_arg->wrapper_closure); if (pick_done) { /* synchronous grpc_lb_policy_pick call. Unref the RR policy. */ if (grpc_lb_glb_trace) { @@ -567,7 +610,12 @@ static bool pick_from_internal_rr_locked( pick_args->lb_token_mdelem_storage, GRPC_MDELEM_REF(wc_arg->lb_token)); - gpr_free(wc_arg); + // Pass on client stats via context. Passes ownership of the reference. + GPR_ASSERT(wc_arg->client_stats != NULL); + wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].value = wc_arg->client_stats; + wc_arg->context[GRPC_GRPCLB_CLIENT_STATS].destroy = destroy_client_stats; + + gpr_free(wc_arg->free_when_done); } /* else, the pending pick will be registered and taken care of by the * pending pick list inside the RR policy (glb_policy->rr_policy). @@ -690,6 +738,8 @@ static void rr_handover_locked(grpc_exec_ctx *exec_ctx, glb_policy->pending_picks = pp->next; GRPC_LB_POLICY_REF(glb_policy->rr_policy, "rr_handover_pending_pick"); pp->wrapped_on_complete_arg.rr_policy = glb_policy->rr_policy; + pp->wrapped_on_complete_arg.client_stats = + grpc_grpclb_client_stats_ref(glb_policy->client_stats); if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, "Pending pick about to PICK from 0x%" PRIxPTR "", (intptr_t)glb_policy->rr_policy); @@ -864,9 +914,22 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, grpc_uri_destroy(uri); glb_policy->cc_factory = args->client_channel_factory; - glb_policy->args = grpc_channel_args_copy(args->args); GPR_ASSERT(glb_policy->cc_factory != NULL); + arg = grpc_channel_args_find(args->args, GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS); + glb_policy->lb_call_timeout_ms = + grpc_channel_arg_get_integer(arg, (grpc_integer_options){0, 0, INT_MAX}); + + // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args, + // since we use this to trigger the client_load_reporting filter. + grpc_arg new_arg; + new_arg.key = GRPC_ARG_LB_POLICY_NAME; + new_arg.type = GRPC_ARG_STRING; + new_arg.value.string = "grpclb"; + static const char *args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME}; + glb_policy->args = grpc_channel_args_copy_and_add_and_remove( + args->args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1); + grpc_slice_hash_table *targets_info = NULL; /* Create a client channel over them to communicate with a LB service */ char *lb_service_target_addresses = @@ -880,6 +943,8 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, grpc_channel_args_destroy(exec_ctx, lb_channel_args); gpr_free(lb_service_target_addresses); if (glb_policy->lb_channel == NULL) { + gpr_free((void *)glb_policy->server_name); + grpc_channel_args_destroy(exec_ctx, glb_policy->args); gpr_free(glb_policy); return NULL; } @@ -895,6 +960,9 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { GPR_ASSERT(glb_policy->pending_pings == NULL); gpr_free((void *)glb_policy->server_name); grpc_channel_args_destroy(exec_ctx, glb_policy->args); + if (glb_policy->client_stats != NULL) { + grpc_grpclb_client_stats_unref(glb_policy->client_stats); + } grpc_channel_destroy(glb_policy->lb_channel); glb_policy->lb_channel = NULL; grpc_connectivity_state_destroy(exec_ctx, &glb_policy->state_tracker); @@ -1011,7 +1079,8 @@ static void glb_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, void **user_data, + grpc_connected_subchannel **target, + grpc_call_context_element *context, void **user_data, grpc_closure *on_complete) { if (pick_args->lb_token_mdelem_storage == NULL) { *target = NULL; @@ -1023,7 +1092,6 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, } glb_lb_policy *glb_policy = (glb_lb_policy *)pol; - glb_policy->deadline = pick_args->deadline; bool pick_done; if (glb_policy->rr_policy != NULL) { @@ -1039,6 +1107,10 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, grpc_schedule_on_exec_ctx); wc_arg->rr_policy = glb_policy->rr_policy; wc_arg->target = target; + wc_arg->context = context; + GPR_ASSERT(glb_policy->client_stats != NULL); + wc_arg->client_stats = + grpc_grpclb_client_stats_ref(glb_policy->client_stats); wc_arg->wrapped_closure = on_complete; wc_arg->lb_token_mdelem_storage = pick_args->lb_token_mdelem_storage; wc_arg->initial_metadata = pick_args->initial_metadata; @@ -1052,7 +1124,7 @@ static int glb_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, "picks", (void *)(glb_policy)); } - add_pending_pick(&glb_policy->pending_picks, pick_args, target, + add_pending_pick(&glb_policy->pending_picks, pick_args, target, context, on_complete); if (!glb_policy->started_picking) { @@ -1093,6 +1165,104 @@ static void glb_notify_on_state_change_locked(grpc_exec_ctx *exec_ctx, exec_ctx, &glb_policy->state_tracker, current, notify); } +static void send_client_load_report_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error); + +static void schedule_next_client_load_report(grpc_exec_ctx *exec_ctx, + glb_lb_policy *glb_policy) { + const gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); + const gpr_timespec next_client_load_report_time = + gpr_time_add(now, glb_policy->client_stats_report_interval); + grpc_closure_init(&glb_policy->client_load_report_closure, + send_client_load_report_locked, glb_policy, + grpc_combiner_scheduler(glb_policy->base.combiner, false)); + grpc_timer_init(exec_ctx, &glb_policy->client_load_report_timer, + next_client_load_report_time, + &glb_policy->client_load_report_closure, now); +} + +static void client_load_report_done_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + glb_lb_policy *glb_policy = arg; + grpc_byte_buffer_destroy(glb_policy->client_load_report_payload); + glb_policy->client_load_report_payload = NULL; + if (error != GRPC_ERROR_NONE || glb_policy->lb_call == NULL) { + glb_policy->client_load_report_timer_pending = false; + GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, + "client_load_report"); + return; + } + schedule_next_client_load_report(exec_ctx, glb_policy); +} + +static void do_send_client_load_report_locked(grpc_exec_ctx *exec_ctx, + glb_lb_policy *glb_policy) { + grpc_op op; + memset(&op, 0, sizeof(op)); + op.op = GRPC_OP_SEND_MESSAGE; + op.data.send_message.send_message = glb_policy->client_load_report_payload; + grpc_closure_init(&glb_policy->client_load_report_closure, + client_load_report_done_locked, glb_policy, + grpc_combiner_scheduler(glb_policy->base.combiner, false)); + grpc_call_error call_error = grpc_call_start_batch_and_execute( + exec_ctx, glb_policy->lb_call, &op, 1, + &glb_policy->client_load_report_closure); + GPR_ASSERT(GRPC_CALL_OK == call_error); +} + +static bool load_report_counters_are_zero(grpc_grpclb_request *request) { + return request->client_stats.num_calls_started == 0 && + request->client_stats.num_calls_finished == 0 && + request->client_stats.num_calls_finished_with_drop_for_rate_limiting == + 0 && + request->client_stats + .num_calls_finished_with_drop_for_load_balancing == 0 && + request->client_stats.num_calls_finished_with_client_failed_to_send == + 0 && + request->client_stats.num_calls_finished_known_received == 0; +} + +static void send_client_load_report_locked(grpc_exec_ctx *exec_ctx, void *arg, + grpc_error *error) { + glb_lb_policy *glb_policy = arg; + if (error == GRPC_ERROR_CANCELLED || glb_policy->lb_call == NULL) { + glb_policy->client_load_report_timer_pending = false; + GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, + "client_load_report"); + return; + } + // Construct message payload. + GPR_ASSERT(glb_policy->client_load_report_payload == NULL); + grpc_grpclb_request *request = + grpc_grpclb_load_report_request_create(glb_policy->client_stats); + // Skip client load report if the counters were all zero in the last + // report and they are still zero in this one. + if (load_report_counters_are_zero(request)) { + if (glb_policy->last_client_load_report_counters_were_zero) { + grpc_grpclb_request_destroy(request); + schedule_next_client_load_report(exec_ctx, glb_policy); + return; + } + glb_policy->last_client_load_report_counters_were_zero = true; + } else { + glb_policy->last_client_load_report_counters_were_zero = false; + } + grpc_slice request_payload_slice = grpc_grpclb_request_encode(request); + glb_policy->client_load_report_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_slice_unref_internal(exec_ctx, request_payload_slice); + grpc_grpclb_request_destroy(request); + // If we've already sent the initial request, then we can go ahead and + // sent the load report. Otherwise, we need to wait until the initial + // request has been sent to send this + // (see lb_on_sent_initial_request_locked() below). + if (glb_policy->initial_request_sent) { + do_send_client_load_report_locked(exec_ctx, glb_policy); + } +} + +static void lb_on_sent_initial_request_locked(grpc_exec_ctx *exec_ctx, + void *arg, grpc_error *error); static void lb_on_server_status_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, @@ -1107,13 +1277,24 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx, * glb_policy->base.interested_parties, which is comprised of the polling * entities from \a client_channel. */ grpc_slice host = grpc_slice_from_copied_string(glb_policy->server_name); + gpr_timespec deadline = + glb_policy->lb_call_timeout_ms == 0 + ? gpr_inf_future(GPR_CLOCK_MONOTONIC) + : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), + gpr_time_from_millis(glb_policy->lb_call_timeout_ms, + GPR_TIMESPAN)); glb_policy->lb_call = grpc_channel_create_pollset_set_call( exec_ctx, glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS, glb_policy->base.interested_parties, GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD, - &host, glb_policy->deadline, NULL); + &host, deadline, NULL); grpc_slice_unref_internal(exec_ctx, host); + if (glb_policy->client_stats != NULL) { + grpc_grpclb_client_stats_unref(glb_policy->client_stats); + } + glb_policy->client_stats = grpc_grpclb_client_stats_create(); + grpc_metadata_array_init(&glb_policy->lb_initial_metadata_recv); grpc_metadata_array_init(&glb_policy->lb_trailing_metadata_recv); @@ -1125,6 +1306,9 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx, grpc_slice_unref_internal(exec_ctx, request_payload_slice); grpc_grpclb_request_destroy(request); + grpc_closure_init(&glb_policy->lb_on_sent_initial_request, + lb_on_sent_initial_request_locked, glb_policy, + grpc_combiner_scheduler(glb_policy->base.combiner, false)); grpc_closure_init(&glb_policy->lb_on_server_status_received, lb_on_server_status_received_locked, glb_policy, grpc_combiner_scheduler(glb_policy->base.combiner, false)); @@ -1138,6 +1322,10 @@ static void lb_call_init_locked(grpc_exec_ctx *exec_ctx, GRPC_GRPCLB_RECONNECT_JITTER, GRPC_GRPCLB_MIN_CONNECT_TIMEOUT_SECONDS * 1000, GRPC_GRPCLB_RECONNECT_MAX_BACKOFF_SECONDS * 1000); + + glb_policy->initial_request_sent = false; + glb_policy->seen_initial_response = false; + glb_policy->last_client_load_report_counters_were_zero = false; } static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx, @@ -1151,6 +1339,10 @@ static void lb_call_destroy_locked(grpc_exec_ctx *exec_ctx, grpc_byte_buffer_destroy(glb_policy->lb_request_payload); grpc_slice_unref_internal(exec_ctx, glb_policy->lb_call_status_details); + + if (!glb_policy->client_load_report_timer_pending) { + grpc_timer_cancel(exec_ctx, &glb_policy->client_load_report_timer); + } } /* @@ -1179,21 +1371,27 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx, op->flags = 0; op->reserved = NULL; op++; - op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &glb_policy->lb_initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; - GPR_ASSERT(glb_policy->lb_request_payload != NULL); op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = glb_policy->lb_request_payload; op->flags = 0; op->reserved = NULL; op++; + /* take a weak ref (won't prevent calling of \a glb_shutdown if the strong ref + * count goes to zero) to be unref'd in lb_on_sent_initial_request_locked() */ + GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "lb_on_server_status_received"); + call_error = grpc_call_start_batch_and_execute( + exec_ctx, glb_policy->lb_call, ops, (size_t)(op - ops), + &glb_policy->lb_on_sent_initial_request); + GPR_ASSERT(GRPC_CALL_OK == call_error); + op = ops; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &glb_policy->lb_trailing_metadata_recv; @@ -1225,6 +1423,19 @@ static void query_for_backends_locked(grpc_exec_ctx *exec_ctx, GPR_ASSERT(GRPC_CALL_OK == call_error); } +static void lb_on_sent_initial_request_locked(grpc_exec_ctx *exec_ctx, + void *arg, grpc_error *error) { + glb_lb_policy *glb_policy = arg; + glb_policy->initial_request_sent = true; + // If we attempted to send a client load report before the initial + // request was sent, send the load report now. + if (glb_policy->client_load_report_payload != NULL) { + do_send_client_load_report_locked(exec_ctx, glb_policy); + } + GRPC_LB_POLICY_WEAK_UNREF(exec_ctx, &glb_policy->base, + "lb_on_response_received_locked"); +} + static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { glb_lb_policy *glb_policy = arg; @@ -1240,58 +1451,91 @@ static void lb_on_response_received_locked(grpc_exec_ctx *exec_ctx, void *arg, grpc_byte_buffer_reader_init(&bbr, glb_policy->lb_response_payload); grpc_slice response_slice = grpc_byte_buffer_reader_readall(&bbr); grpc_byte_buffer_destroy(glb_policy->lb_response_payload); - grpc_grpclb_serverlist *serverlist = - grpc_grpclb_response_parse_serverlist(response_slice); - if (serverlist != NULL) { - GPR_ASSERT(glb_policy->lb_call != NULL); - grpc_slice_unref_internal(exec_ctx, response_slice); - if (grpc_lb_glb_trace) { - gpr_log(GPR_INFO, "Serverlist with %lu servers received", - (unsigned long)serverlist->num_servers); - for (size_t i = 0; i < serverlist->num_servers; ++i) { - grpc_resolved_address addr; - parse_server(serverlist->servers[i], &addr); - char *ipport; - grpc_sockaddr_to_string(&ipport, &addr, false); - gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport); - gpr_free(ipport); + + grpc_grpclb_initial_response *response = NULL; + if (!glb_policy->seen_initial_response && + (response = grpc_grpclb_initial_response_parse(response_slice)) != + NULL) { + if (response->has_client_stats_report_interval) { + glb_policy->client_stats_report_interval = + gpr_time_max(gpr_time_from_seconds(1, GPR_TIMESPAN), + grpc_grpclb_duration_to_timespec( + &response->client_stats_report_interval)); + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "received initial LB response message; " + "client load reporting interval = %" PRId64 ".%09d sec", + glb_policy->client_stats_report_interval.tv_sec, + glb_policy->client_stats_report_interval.tv_nsec); } + /* take a weak ref (won't prevent calling of \a glb_shutdown() if the + * strong ref count goes to zero) to be unref'd in + * send_client_load_report() */ + glb_policy->client_load_report_timer_pending = true; + GRPC_LB_POLICY_WEAK_REF(&glb_policy->base, "client_load_report"); + schedule_next_client_load_report(exec_ctx, glb_policy); + } else if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "received initial LB response message; " + "client load reporting NOT enabled"); } + grpc_grpclb_initial_response_destroy(response); + glb_policy->seen_initial_response = true; + } else { + grpc_grpclb_serverlist *serverlist = + grpc_grpclb_response_parse_serverlist(response_slice); + if (serverlist != NULL) { + GPR_ASSERT(glb_policy->lb_call != NULL); + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, "Serverlist with %lu servers received", + (unsigned long)serverlist->num_servers); + for (size_t i = 0; i < serverlist->num_servers; ++i) { + grpc_resolved_address addr; + parse_server(serverlist->servers[i], &addr); + char *ipport; + grpc_sockaddr_to_string(&ipport, &addr, false); + gpr_log(GPR_INFO, "Serverlist[%lu]: %s", (unsigned long)i, ipport); + gpr_free(ipport); + } + } - /* update serverlist */ - if (serverlist->num_servers > 0) { - if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, serverlist)) { + /* update serverlist */ + if (serverlist->num_servers > 0) { + if (grpc_grpclb_serverlist_equals(glb_policy->serverlist, + serverlist)) { + if (grpc_lb_glb_trace) { + gpr_log(GPR_INFO, + "Incoming server list identical to current, ignoring."); + } + grpc_grpclb_destroy_serverlist(serverlist); + } else { /* new serverlist */ + if (glb_policy->serverlist != NULL) { + /* dispose of the old serverlist */ + grpc_grpclb_destroy_serverlist(glb_policy->serverlist); + } + /* and update the copy in the glb_lb_policy instance. This + * serverlist instance will be destroyed either upon the next + * update or in glb_destroy() */ + glb_policy->serverlist = serverlist; + + rr_handover_locked(exec_ctx, glb_policy); + } + } else { if (grpc_lb_glb_trace) { gpr_log(GPR_INFO, - "Incoming server list identical to current, ignoring."); + "Received empty server list. Picks will stay pending until " + "a response with > 0 servers is received"); } grpc_grpclb_destroy_serverlist(serverlist); - } else { /* new serverlist */ - if (glb_policy->serverlist != NULL) { - /* dispose of the old serverlist */ - grpc_grpclb_destroy_serverlist(glb_policy->serverlist); - } - /* and update the copy in the glb_lb_policy instance. This serverlist - * instance will be destroyed either upon the next update or in - * glb_destroy() */ - glb_policy->serverlist = serverlist; - - rr_handover_locked(exec_ctx, glb_policy); } - } else { - if (grpc_lb_glb_trace) { - gpr_log(GPR_INFO, - "Received empty server list. Picks will stay pending until a " - "response with > 0 servers is received"); - } - grpc_grpclb_destroy_serverlist(glb_policy->serverlist); + } else { /* serverlist == NULL */ + gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.", + grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX)); } - } else { /* serverlist == NULL */ - gpr_log(GPR_ERROR, "Invalid LB response received: '%s'. Ignoring.", - grpc_dump_slice(response_slice, GPR_DUMP_ASCII | GPR_DUMP_HEX)); - grpc_slice_unref_internal(exec_ctx, response_slice); } + grpc_slice_unref_internal(exec_ctx, response_slice); + if (!glb_policy->shutting_down) { /* keep listening for serverlist updates */ op->op = GRPC_OP_RECV_MESSAGE; @@ -1403,9 +1647,29 @@ grpc_lb_policy_factory *grpc_glb_lb_factory_create() { } /* Plugin registration */ + +// Only add client_load_reporting filter if the grpclb LB policy is used. +static bool maybe_add_client_load_reporting_filter( + grpc_exec_ctx *exec_ctx, grpc_channel_stack_builder *builder, void *arg) { + const grpc_channel_args *args = + grpc_channel_stack_builder_get_channel_arguments(builder); + const grpc_arg *channel_arg = + grpc_channel_args_find(args, GRPC_ARG_LB_POLICY_NAME); + if (channel_arg != NULL && channel_arg->type == GRPC_ARG_STRING && + strcmp(channel_arg->value.string, "grpclb") == 0) { + return grpc_channel_stack_builder_append_filter( + builder, (const grpc_channel_filter *)arg, NULL, NULL); + } + return true; +} + void grpc_lb_policy_grpclb_init() { grpc_register_lb_policy(grpc_glb_lb_factory_create()); grpc_register_tracer("glb", &grpc_lb_glb_trace); + grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, + GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, + maybe_add_client_load_reporting_filter, + (void *)&grpc_client_load_reporting_filter); } void grpc_lb_policy_grpclb_shutdown() {} diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c new file mode 100644 index 00000000000..444c03b9aab --- /dev/null +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c @@ -0,0 +1,133 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" + +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" + +#define GRPC_ARG_GRPCLB_CLIENT_STATS "grpc.grpclb_client_stats" + +struct grpc_grpclb_client_stats { + gpr_refcount refs; + gpr_atm num_calls_started; + gpr_atm num_calls_finished; + gpr_atm num_calls_finished_with_drop_for_rate_limiting; + gpr_atm num_calls_finished_with_drop_for_load_balancing; + gpr_atm num_calls_finished_with_client_failed_to_send; + gpr_atm num_calls_finished_known_received; +}; + +grpc_grpclb_client_stats* grpc_grpclb_client_stats_create() { + grpc_grpclb_client_stats* client_stats = gpr_zalloc(sizeof(*client_stats)); + gpr_ref_init(&client_stats->refs, 1); + return client_stats; +} + +grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref( + grpc_grpclb_client_stats* client_stats) { + gpr_ref(&client_stats->refs); + return client_stats; +} + +void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats) { + if (gpr_unref(&client_stats->refs)) { + gpr_free(client_stats); + } +} + +void grpc_grpclb_client_stats_add_call_started( + grpc_grpclb_client_stats* client_stats) { + gpr_atm_full_fetch_add(&client_stats->num_calls_started, (gpr_atm)1); +} + +void grpc_grpclb_client_stats_add_call_finished( + bool finished_with_drop_for_rate_limiting, + bool finished_with_drop_for_load_balancing, + bool finished_with_client_failed_to_send, bool finished_known_received, + grpc_grpclb_client_stats* client_stats) { + gpr_atm_full_fetch_add(&client_stats->num_calls_finished, (gpr_atm)1); + if (finished_with_drop_for_rate_limiting) { + gpr_atm_full_fetch_add( + &client_stats->num_calls_finished_with_drop_for_rate_limiting, + (gpr_atm)1); + } + if (finished_with_drop_for_load_balancing) { + gpr_atm_full_fetch_add( + &client_stats->num_calls_finished_with_drop_for_load_balancing, + (gpr_atm)1); + } + if (finished_with_client_failed_to_send) { + gpr_atm_full_fetch_add( + &client_stats->num_calls_finished_with_client_failed_to_send, + (gpr_atm)1); + } + if (finished_known_received) { + gpr_atm_full_fetch_add(&client_stats->num_calls_finished_known_received, + (gpr_atm)1); + } +} + +static void atomic_get_and_reset_counter(int64_t* value, gpr_atm* counter) { + *value = (int64_t)gpr_atm_acq_load(counter); + gpr_atm_full_fetch_add(counter, (gpr_atm)(-*value)); +} + +void grpc_grpclb_client_stats_get( + grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started, + int64_t* num_calls_finished, + int64_t* num_calls_finished_with_drop_for_rate_limiting, + int64_t* num_calls_finished_with_drop_for_load_balancing, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received) { + atomic_get_and_reset_counter(num_calls_started, + &client_stats->num_calls_started); + atomic_get_and_reset_counter(num_calls_finished, + &client_stats->num_calls_finished); + atomic_get_and_reset_counter( + num_calls_finished_with_drop_for_rate_limiting, + &client_stats->num_calls_finished_with_drop_for_rate_limiting); + atomic_get_and_reset_counter( + num_calls_finished_with_drop_for_load_balancing, + &client_stats->num_calls_finished_with_drop_for_load_balancing); + atomic_get_and_reset_counter( + num_calls_finished_with_client_failed_to_send, + &client_stats->num_calls_finished_with_client_failed_to_send); + atomic_get_and_reset_counter( + num_calls_finished_known_received, + &client_stats->num_calls_finished_known_received); +} 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 new file mode 100644 index 00000000000..0af4a919f80 --- /dev/null +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -0,0 +1,65 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CLIENT_STATS_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CLIENT_STATS_H + +#include + +#include + +typedef struct grpc_grpclb_client_stats grpc_grpclb_client_stats; + +grpc_grpclb_client_stats* grpc_grpclb_client_stats_create(); +grpc_grpclb_client_stats* grpc_grpclb_client_stats_ref( + grpc_grpclb_client_stats* client_stats); +void grpc_grpclb_client_stats_unref(grpc_grpclb_client_stats* client_stats); + +void grpc_grpclb_client_stats_add_call_started( + grpc_grpclb_client_stats* client_stats); +void grpc_grpclb_client_stats_add_call_finished( + bool finished_with_drop_for_rate_limiting, + bool finished_with_drop_for_load_balancing, + bool finished_with_client_failed_to_send, bool finished_known_received, + grpc_grpclb_client_stats* client_stats); + +void grpc_grpclb_client_stats_get( + grpc_grpclb_client_stats* client_stats, int64_t* num_calls_started, + int64_t* num_calls_finished, + int64_t* num_calls_finished_with_drop_for_rate_limiting, + int64_t* num_calls_finished_with_drop_for_load_balancing, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received); + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_CLIENT_STATS_H \ + */ diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c index 87549b78f0e..81b6932faeb 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c @@ -80,15 +80,45 @@ static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field, grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name) { grpc_grpclb_request *req = gpr_malloc(sizeof(grpc_grpclb_request)); - - req->has_client_stats = 0; /* TODO(dgq): add support for stats once defined */ - req->has_initial_request = 1; - req->initial_request.has_name = 1; + req->has_client_stats = false; + req->has_initial_request = true; + req->initial_request.has_name = true; strncpy(req->initial_request.name, lb_service_name, GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH); return req; } +static void populate_timestamp(gpr_timespec timestamp, + struct _grpc_lb_v1_Timestamp *timestamp_pb) { + timestamp_pb->has_seconds = true; + timestamp_pb->seconds = timestamp.tv_sec; + timestamp_pb->has_nanos = true; + timestamp_pb->nanos = timestamp.tv_nsec; +} + +grpc_grpclb_request *grpc_grpclb_load_report_request_create( + grpc_grpclb_client_stats *client_stats) { + grpc_grpclb_request *req = gpr_zalloc(sizeof(grpc_grpclb_request)); + req->has_client_stats = true; + req->client_stats.has_timestamp = true; + populate_timestamp(gpr_now(GPR_CLOCK_REALTIME), &req->client_stats.timestamp); + req->client_stats.has_num_calls_started = true; + req->client_stats.has_num_calls_finished = true; + req->client_stats.has_num_calls_finished_with_drop_for_rate_limiting = true; + req->client_stats.has_num_calls_finished_with_drop_for_load_balancing = true; + req->client_stats.has_num_calls_finished_with_client_failed_to_send = true; + req->client_stats.has_num_calls_finished_with_client_failed_to_send = true; + req->client_stats.has_num_calls_finished_known_received = true; + grpc_grpclb_client_stats_get( + client_stats, &req->client_stats.num_calls_started, + &req->client_stats.num_calls_finished, + &req->client_stats.num_calls_finished_with_drop_for_rate_limiting, + &req->client_stats.num_calls_finished_with_drop_for_load_balancing, + &req->client_stats.num_calls_finished_with_client_failed_to_send, + &req->client_stats.num_calls_finished_known_received); + return req; +} + grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) { size_t encoded_length; pb_ostream_t sizestream; @@ -122,6 +152,9 @@ grpc_grpclb_initial_response *grpc_grpclb_initial_response_parse( gpr_log(GPR_ERROR, "nanopb error: %s", PB_GET_ERROR(&stream)); return NULL; } + + if (!res.has_initial_response) return NULL; + grpc_grpclb_initial_response *initial_res = gpr_malloc(sizeof(grpc_grpclb_initial_response)); memcpy(initial_res, &res.initial_response, @@ -243,6 +276,15 @@ int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs, return 0; } +gpr_timespec grpc_grpclb_duration_to_timespec( + grpc_grpclb_duration *duration_pb) { + gpr_timespec duration; + duration.tv_sec = duration_pb->has_seconds ? duration_pb->seconds : 0; + duration.tv_nsec = duration_pb->has_nanos ? duration_pb->nanos : 0; + duration.clock_type = GPR_TIMESPAN; + return duration; +} + void grpc_grpclb_initial_response_destroy( grpc_grpclb_initial_response *response) { gpr_free(response); diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h index d014b8800ca..06873821bd3 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h @@ -36,6 +36,7 @@ #include +#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h" @@ -58,6 +59,8 @@ typedef struct grpc_grpclb_serverlist { /** Create a request for a gRPC LB service under \a lb_service_name */ grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name); +grpc_grpclb_request *grpc_grpclb_load_report_request_create( + grpc_grpclb_client_stats *client_stats); /** Protocol Buffers v3-encode \a request */ grpc_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request); @@ -93,6 +96,9 @@ void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist); int grpc_grpclb_duration_compare(const grpc_grpclb_duration *lhs, const grpc_grpclb_duration *rhs); +gpr_timespec grpc_grpclb_duration_to_timespec( + grpc_grpclb_duration *duration_pb); + /** Destroy \a initial_response */ void grpc_grpclb_initial_response_destroy( grpc_grpclb_initial_response *response); diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c index 2b77cd39b84..b1c5dfc61ca 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c @@ -189,7 +189,8 @@ static void pf_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int pf_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, void **user_data, + grpc_connected_subchannel **target, + grpc_call_context_element *context, void **user_data, grpc_closure *on_complete) { pick_first_lb_policy *p = (pick_first_lb_policy *)pol; pending_pick *pp; diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c index ff41e61b3e6..4c17f9c0828 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c @@ -414,7 +414,8 @@ static void rr_exit_idle_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) { static int rr_pick_locked(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol, const grpc_lb_policy_pick_args *pick_args, - grpc_connected_subchannel **target, void **user_data, + grpc_connected_subchannel **target, + grpc_call_context_element *context, void **user_data, grpc_closure *on_complete) { round_robin_lb_policy *p = (round_robin_lb_policy *)pol; pending_pick *pp; diff --git a/src/core/ext/filters/client_channel/subchannel.c b/src/core/ext/filters/client_channel/subchannel.c index b2de85c4a12..1af3393a62c 100644 --- a/src/core/ext/filters/client_channel/subchannel.c +++ b/src/core/ext/filters/client_channel/subchannel.c @@ -781,7 +781,7 @@ grpc_error *grpc_connected_subchannel_create_call( (*call)->connection = GRPC_CONNECTED_SUBCHANNEL_REF(con, "subchannel_call"); const grpc_call_element_args call_args = {.call_stack = callstk, .server_transport_data = NULL, - .context = NULL, + .context = args->context, .path = args->path, .start_time = args->start_time, .deadline = args->deadline, diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 6473de49b0b..e433c33e408 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -119,6 +119,7 @@ typedef struct { gpr_timespec start_time; gpr_timespec deadline; gpr_arena *arena; + grpc_call_context_element *context; } grpc_connected_subchannel_call_args; grpc_error *grpc_connected_subchannel_create_call( diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c index d4e89d6a6cb..67974b0b6a6 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.c +++ b/src/core/ext/transport/cronet/transport/cronet_transport.c @@ -886,6 +886,10 @@ static bool op_can_be_run(grpc_transport_stream_op_batch *curr_op, !stream_state->state_op_done[OP_RECV_MESSAGE]) { CRONET_LOG(GPR_DEBUG, "Because"); result = false; + } else if (curr_op->cancel_stream && + !stream_state->state_callback_received[OP_CANCELED]) { + CRONET_LOG(GPR_DEBUG, "Because"); + result = false; } else if (curr_op->recv_trailing_metadata) { /* We aren't done with trailing metadata yet */ if (!stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) { diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h index 6c931ad28ae..f0a21113c53 100644 --- a/src/core/lib/channel/context.h +++ b/src/core/lib/channel/context.h @@ -50,6 +50,9 @@ typedef enum { /// Reserved for traffic_class_context. GRPC_CONTEXT_TRAFFIC, + /// Value is a \a grpc_grpclb_client_stats. + GRPC_GRPCLB_CLIENT_STATS, + GRPC_CONTEXT_COUNT } grpc_context_index; diff --git a/src/core/lib/http/httpcli.c b/src/core/lib/http/httpcli.c index 453a64b0495..0ac2c2ad52a 100644 --- a/src/core/lib/http/httpcli.c +++ b/src/core/lib/http/httpcli.c @@ -105,7 +105,7 @@ static void finish(grpc_exec_ctx *exec_ctx, internal_request *req, grpc_error *error) { grpc_polling_entity_del_from_pollset_set(exec_ctx, req->pollent, req->context->pollset_set); - grpc_closure_sched(exec_ctx, req->on_done, error); + grpc_closure_sched(exec_ctx, req->on_done, GRPC_ERROR_REF(error)); grpc_http_parser_destroy(&req->parser); if (req->addresses != NULL) { grpc_resolved_addresses_destroy(req->addresses); diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 269dc35003e..2a553f41149 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -88,6 +88,7 @@ #ifndef __GLIBC__ #define GRPC_LINUX_EPOLL 1 #define GRPC_LINUX_EVENTFD 1 +#define GRPC_MSG_IOVLEN_TYPE int #endif #ifndef GRPC_LINUX_EVENTFD #define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1 diff --git a/src/core/lib/support/cpu_linux.c b/src/core/lib/support/cpu_linux.c index 1e50f59823f..b826dde1601 100644 --- a/src/core/lib/support/cpu_linux.c +++ b/src/core/lib/support/cpu_linux.c @@ -67,16 +67,16 @@ unsigned gpr_cpu_num_cores(void) { } unsigned gpr_cpu_current_cpu(void) { -#ifdef __GLIBC__ +#ifdef GPR_MUSL_LIBC_COMPAT + // sched_getcpu() is undefined on musl + return 0; +#else int cpu = sched_getcpu(); if (cpu < 0) { gpr_log(GPR_ERROR, "Error determining current CPU: %s\n", strerror(errno)); return 0; } return (unsigned)cpu; -#else - // sched_getcpu() is undefined on musl - return 0; #endif } diff --git a/src/core/lib/support/wrap_memcpy.c b/src/core/lib/support/wrap_memcpy.c index 050cc6db5ec..deb8d6b198a 100644 --- a/src/core/lib/support/wrap_memcpy.c +++ b/src/core/lib/support/wrap_memcpy.c @@ -31,6 +31,8 @@ * */ +#include + #include /* Provide a wrapped memcpy for targets that need to be backwards @@ -40,7 +42,7 @@ */ #ifdef __linux__ -#if defined(__x86_64__) && defined(__GNU_LIBRARY__) +#if defined(__x86_64__) && !defined(GPR_MUSL_LIBC_COMPAT) __asm__(".symver memcpy,memcpy@GLIBC_2.2.5"); void *__wrap_memcpy(void *destination, const void *source, size_t num) { return memcpy(destination, source, num); diff --git a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs index b9c0fe6d0d8..c9f7c42b71d 100644 --- a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs +++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs @@ -179,6 +179,9 @@ namespace Grpc.IntegrationTesting statsResetCount.Increment(); } + GrpcEnvironment.Logger.Info("[ClientRunnerImpl.GetStats] GC collection counts: gen0 {0}, gen1 {1}, gen2 {2}, gen3 {3} (histogram reset count:{4}, seconds since reset: {5})", + GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), GC.CollectionCount(3), statsResetCount.Count, secondsElapsed); + // TODO: populate user time and system time return new ClientStats { diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs index b17b2c2183a..486befe964c 100644 --- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs +++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs @@ -95,10 +95,13 @@ namespace Grpc.IntegrationTesting Ports = { new ServerPort(host, options.DriverPort, ServerCredentials.Insecure )} }; int boundPort = server.Ports.Single().BoundPort; - Console.WriteLine("Running qps worker server on " + string.Format("{0}:{1}", host, boundPort)); + GrpcEnvironment.Logger.Info("Running qps worker server on {0}:{1}", host, boundPort); server.Start(); await tcs.Task; await server.ShutdownAsync(); + + GrpcEnvironment.Logger.Info("GC collection counts (after shutdown): gen0 {0}, gen1 {1}, gen2 {2}, gen3 {3}", + GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), GC.CollectionCount(3)); } } } diff --git a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs index 8689d188aed..7ab77347005 100644 --- a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs +++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs @@ -154,6 +154,9 @@ namespace Grpc.IntegrationTesting { var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds; + GrpcEnvironment.Logger.Info("[ServerRunner.GetStats] GC collection counts: gen0 {0}, gen1 {1}, gen2 {2}, gen3 {3} (seconds since last reset {4})", + GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), GC.CollectionCount(3), secondsElapsed); + // TODO: populate user time and system time return new ServerStats { diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index fe0c80e6421..49179ab3596 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -42,7 +42,6 @@ #include "call_credentials.h" #include "channel.h" #include "completion_queue.h" -#include "completion_queue_async_worker.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/alloc.h" diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc index be04cf421d6..eb6bc0f53fe 100644 --- a/src/node/ext/channel.cc +++ b/src/node/ext/channel.cc @@ -41,7 +41,6 @@ #include "channel.h" #include "channel_credentials.h" #include "completion_queue.h" -#include "completion_queue_async_worker.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "timeval.h" diff --git a/src/node/ext/completion_queue_uv.cc b/src/node/ext/completion_queue.cc similarity index 98% rename from src/node/ext/completion_queue_uv.cc rename to src/node/ext/completion_queue.cc index 9b60911d1e9..d01abad7572 100644 --- a/src/node/ext/completion_queue_uv.cc +++ b/src/node/ext/completion_queue.cc @@ -31,8 +31,6 @@ * */ -#ifdef GRPC_UV - #include #include #include @@ -95,5 +93,3 @@ void CompletionQueueInit(Local exports) { } // namespace node } // namespace grpc - -#endif /* GRPC_UV */ diff --git a/src/node/ext/completion_queue_async_worker.h b/src/node/ext/completion_queue_async_worker.h deleted file mode 100644 index 6e541167658..00000000000 --- a/src/node/ext/completion_queue_async_worker.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_ -#define NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_ -#include - -#include "grpc/grpc.h" - -namespace grpc { -namespace node { - -/* A worker that asynchronously calls completion_queue_next, and queues onto the - node event loop a call to the function stored in the event's tag. */ -class CompletionQueueAsyncWorker : public Nan::AsyncWorker { - public: - CompletionQueueAsyncWorker(); - - ~CompletionQueueAsyncWorker(); - /* Calls completion_queue_next with the provided deadline, and stores the - event if there was one or sets an error message if there was not */ - void Execute(); - - /* Returns the completion queue attached to this class */ - static grpc_completion_queue *GetQueue(); - - /* Convenience function to create a worker with the given arguments and queue - it to run asynchronously */ - static void Next(); - - /* Initialize the CompletionQueueAsyncWorker class */ - static void Init(v8::Local exports); - - protected: - /* Called when Execute has succeeded (completed without setting an error - message). Calls the saved callback with the event that came from - completion_queue_next */ - void HandleOKCallback(); - - void HandleErrorCallback(); - - private: - grpc_event result; - - static grpc_completion_queue *queue; - - // Number of grpc_completion_queue_next calls in the thread pool - static int current_threads; - // Number of grpc_completion_queue_next calls waiting to enter the thread pool - static int waiting_next_calls; -}; - -} // namespace node -} // namespace grpc - -#endif // NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_ diff --git a/src/node/ext/completion_queue_threadpool.cc b/src/node/ext/completion_queue_threadpool.cc deleted file mode 100644 index 72df5d1d65f..00000000000 --- a/src/node/ext/completion_queue_threadpool.cc +++ /dev/null @@ -1,180 +0,0 @@ -/* - * - * Copyright 2015, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -/* I don't like using #ifndef, but I don't see a better way to do this */ -#ifndef GRPC_UV - -#include -#include - -#include "call.h" -#include "completion_queue.h" -#include "grpc/grpc.h" -#include "grpc/support/log.h" -#include "grpc/support/time.h" - -namespace grpc { -namespace node { - -namespace { - -/* A worker that asynchronously calls completion_queue_next, and queues onto the - node event loop a call to the function stored in the event's tag. */ -class CompletionQueueAsyncWorker : public Nan::AsyncWorker { - public: - CompletionQueueAsyncWorker(); - - ~CompletionQueueAsyncWorker(); - /* Calls completion_queue_next with the provided deadline, and stores the - event if there was one or sets an error message if there was not */ - void Execute(); - - /* Returns the completion queue attached to this class */ - static grpc_completion_queue *GetQueue(); - - /* Convenience function to create a worker with the given arguments and queue - it to run asynchronously */ - static void Next(); - - /* Initialize the CompletionQueueAsyncWorker class */ - static void Init(v8::Local exports); - - protected: - /* Called when Execute has succeeded (completed without setting an error - message). Calls the saved callback with the event that came from - completion_queue_next */ - void HandleOKCallback(); - - void HandleErrorCallback(); - - private: - static void TryAddWorker(); - - grpc_event result; - - static grpc_completion_queue *queue; - - // Number of grpc_completion_queue_next calls in the thread pool - static int current_threads; - // Number of grpc_completion_queue_next calls waiting to enter the thread pool - static int waiting_next_calls; -}; - -const int max_queue_threads = 2; - -using v8::Function; -using v8::Local; -using v8::Object; -using v8::Value; - -grpc_completion_queue *CompletionQueueAsyncWorker::queue; - -// Invariants: current_threads <= max_queue_threads -// (current_threads == max_queue_threads) || (waiting_next_calls == 0) - -int CompletionQueueAsyncWorker::current_threads; -int CompletionQueueAsyncWorker::waiting_next_calls; - -CompletionQueueAsyncWorker::CompletionQueueAsyncWorker() - : Nan::AsyncWorker(NULL) {} - -CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {} - -void CompletionQueueAsyncWorker::Execute() { - result = grpc_completion_queue_next(queue, gpr_inf_future(GPR_CLOCK_REALTIME), - NULL); - if (!result.success) { - SetErrorMessage("The async function encountered an error"); - } -} - -grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; } - -void CompletionQueueAsyncWorker::TryAddWorker() { - if (current_threads < max_queue_threads && waiting_next_calls > 0) { - current_threads += 1; - waiting_next_calls -= 1; - CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker(); - Nan::AsyncQueueWorker(worker); - } - GPR_ASSERT(current_threads <= max_queue_threads); - GPR_ASSERT((current_threads == max_queue_threads) || - (waiting_next_calls == 0)); -} - -void CompletionQueueAsyncWorker::Next() { - waiting_next_calls += 1; - TryAddWorker(); -} - -void CompletionQueueAsyncWorker::Init(Local exports) { - Nan::HandleScope scope; - current_threads = 0; - waiting_next_calls = 0; - queue = grpc_completion_queue_create_for_next(NULL); -} - -void CompletionQueueAsyncWorker::HandleOKCallback() { - Nan::HandleScope scope; - current_threads -= 1; - TryAddWorker(); - CompleteTag(result.tag, NULL); - - DestroyTag(result.tag); -} - -void CompletionQueueAsyncWorker::HandleErrorCallback() { - Nan::HandleScope scope; - current_threads -= 1; - TryAddWorker(); - CompleteTag(result.tag, ErrorMessage()); - - DestroyTag(result.tag); -} - -} // namespace - -grpc_completion_queue *GetCompletionQueue() { - return CompletionQueueAsyncWorker::GetQueue(); -} - -void CompletionQueueNext() { CompletionQueueAsyncWorker::Next(); } - -void CompletionQueueInit(Local exports) { - CompletionQueueAsyncWorker::Init(exports); -} - -} // namespace node -} // namespace grpc - -#endif /* GRPC_UV */ diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc index 076f1ed4242..e193e82179a 100644 --- a/src/node/ext/node_grpc.cc +++ b/src/node/ext/node_grpc.cc @@ -43,18 +43,15 @@ #include "grpc/support/time.h" // TODO(murgatroid99): Remove this when the endpoint API becomes public -#ifdef GRPC_UV extern "C" { #include "src/core/lib/iomgr/pollset_uv.h" } -#endif #include "call.h" #include "call_credentials.h" #include "channel.h" #include "channel_credentials.h" #include "completion_queue.h" -#include "completion_queue_async_worker.h" #include "server.h" #include "server_credentials.h" #include "slice.h" @@ -432,9 +429,7 @@ void init(Local exports) { InitWriteFlags(exports); InitLogConstants(exports); -#ifdef GRPC_UV grpc_pollset_work_run_loop = 0; -#endif grpc::node::Call::Init(exports); grpc::node::CallCredentials::Init(exports); diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 1871a324528..a885a9f2684 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -41,7 +41,6 @@ #include #include "call.h" #include "completion_queue.h" -#include "completion_queue_async_worker.h" #include "grpc/grpc.h" #include "grpc/grpc_security.h" #include "grpc/support/log.h" @@ -78,6 +77,30 @@ using v8::Value; Nan::Callback *Server::constructor; Persistent Server::fun_tpl; +static Callback *shutdown_callback = NULL; + +class ServerShutdownOp : public Op { + public: + ServerShutdownOp(grpc_server *server) : server(server) {} + + ~ServerShutdownOp() {} + + Local GetNodeValue() const { return Nan::Null(); } + + bool ParseOp(Local value, grpc_op *out) { return true; } + bool IsFinalOp() { return false; } + void OnComplete(bool success) { + /* Because cancel_all_calls was called, we assume that shutdown_and_notify + completes successfully */ + grpc_server_destroy(server); + } + + grpc_server *server; + + protected: + std::string GetTypeString() const { return "shutdown"; } +}; + class NewCallOp : public Op { public: NewCallOp() { @@ -149,6 +172,10 @@ class TryShutdownOp : public Op { server_persist; }; +Server::Server(grpc_server *server) : wrapped_server(server) {} + +Server::~Server() { this->ShutdownServer(); } + void Server::Init(Local exports) { HandleScope scope; Local tpl = Nan::New(New); @@ -177,6 +204,36 @@ void Server::DestroyWrappedServer() { } } +NAN_METHOD(ServerShutdownCallback) { + if (!info[0]->IsNull()) { + return Nan::ThrowError("forceShutdown failed somehow"); + } +} + +void Server::ShutdownServer() { + Nan::HandleScope scope; + if (this->wrapped_server != NULL) { + if (shutdown_callback == NULL) { + Local callback_tpl = + Nan::New(ServerShutdownCallback); + shutdown_callback = + new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked()); + } + + ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server); + unique_ptr ops(new OpVec()); + ops->push_back(unique_ptr(op)); + + grpc_server_shutdown_and_notify( + this->wrapped_server, GetCompletionQueue(), + new struct tag(new Callback(**shutdown_callback), ops.release(), NULL, + Nan::Null())); + grpc_server_cancel_all_calls(this->wrapped_server); + CompletionQueueNext(); + this->wrapped_server = NULL; + } +} + NAN_METHOD(Server::New) { /* If this is not a constructor call, make a constructor call and return the result */ diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc deleted file mode 100644 index 709921b7fc1..00000000000 --- a/src/node/ext/server_uv.cc +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Copyright 2017, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifdef GRPC_UV - -#include "server.h" - -#include -#include -#include "grpc/grpc.h" -#include "grpc/support/time.h" - -#include "call.h" -#include "completion_queue.h" - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::MaybeLocal; - -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Local; -using v8::Object; -using v8::Value; - -static Callback *shutdown_callback = NULL; - -class ServerShutdownOp : public Op { - public: - ServerShutdownOp(grpc_server *server) : server(server) {} - - ~ServerShutdownOp() {} - - Local GetNodeValue() const { return Nan::Null(); } - - bool ParseOp(Local value, grpc_op *out) { return true; } - bool IsFinalOp() { return false; } - void OnComplete(bool success) { - /* Because cancel_all_calls was called, we assume that shutdown_and_notify - completes successfully */ - grpc_server_destroy(server); - } - - grpc_server *server; - - protected: - std::string GetTypeString() const { return "shutdown"; } -}; - -Server::Server(grpc_server *server) : wrapped_server(server) {} - -Server::~Server() { this->ShutdownServer(); } - -NAN_METHOD(ServerShutdownCallback) { - if (!info[0]->IsNull()) { - return Nan::ThrowError("forceShutdown failed somehow"); - } -} - -void Server::ShutdownServer() { - Nan::HandleScope scope; - if (this->wrapped_server != NULL) { - if (shutdown_callback == NULL) { - Local callback_tpl = - Nan::New(ServerShutdownCallback); - shutdown_callback = - new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked()); - } - - ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server); - unique_ptr ops(new OpVec()); - ops->push_back(unique_ptr(op)); - - grpc_server_shutdown_and_notify( - this->wrapped_server, GetCompletionQueue(), - new struct tag(new Callback(**shutdown_callback), ops.release(), NULL, - Nan::Null())); - grpc_server_cancel_all_calls(this->wrapped_server); - CompletionQueueNext(); - this->wrapped_server = NULL; - } -} - -} // namespace grpc -} // namespace node - -#endif /* GRPC_UV */ diff --git a/tools/internal_ci/linux/grpc_fuzzer_uri.sh b/src/proto/grpc/lb/v1/BUILD old mode 100755 new mode 100644 similarity index 85% rename from tools/internal_ci/linux/grpc_fuzzer_uri.sh rename to src/proto/grpc/lb/v1/BUILD index 67039f38807..46d4f2d62c7 --- a/tools/internal_ci/linux/grpc_fuzzer_uri.sh +++ b/src/proto/grpc/lb/v1/BUILD @@ -1,4 +1,3 @@ -#!/bin/bash # Copyright 2017, Google Inc. # All rights reserved. # @@ -28,13 +27,13 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -set -ex +licenses(["notice"]) # 3-clause BSD -# change to grpc repo root -cd $(dirname $0)/../../.. +package(default_visibility = ["//visibility:public"]) -git submodule update --init +load("//bazel:grpc_build_system.bzl", "grpc_proto_library") -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -config=asan-trace-cmp tools/jenkins/run_fuzzer.sh uri_fuzzer_test +grpc_proto_library( + name = "load_balancer_proto", + srcs = ["load_balancer.proto"], +) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi index 34b2623d346..502b6556b4e 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi @@ -37,9 +37,16 @@ cdef int _INTERRUPT_CHECK_PERIOD_MS = 200 cdef class CompletionQueue: - def __cinit__(self): + def __cinit__(self, shutdown_cq=False): + cdef grpc_completion_queue_attributes c_attrs grpc_init() - with nogil: + if shutdown_cq: + c_attrs.version = 1 + c_attrs.cq_completion_type = GRPC_CQ_NEXT + c_attrs.cq_polling_type = GRPC_CQ_NON_LISTENING + self.c_completion_queue = grpc_completion_queue_create( + grpc_completion_queue_factory_lookup(&c_attrs), &c_attrs, NULL); + else: self.c_completion_queue = grpc_completion_queue_create_for_next(NULL) self.is_shutting_down = False self.is_shutdown = False diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index f66f6e41223..1db2056d476 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -217,6 +217,20 @@ cdef extern from "grpc/grpc.h": GRPC_CALL_ERROR_INVALID_FLAGS GRPC_CALL_ERROR_INVALID_METADATA + ctypedef enum grpc_cq_completion_type: + GRPC_CQ_NEXT + GRPC_CQ_PLUCK + + ctypedef enum grpc_cq_polling_type: + GRPC_CQ_DEFAULT_POLLING + GRPC_CQ_NON_LISTENING + GRPC_CQ_NON_POLLING + + ctypedef struct grpc_completion_queue_attributes: + int version + grpc_cq_completion_type cq_completion_type + grpc_cq_polling_type cq_polling_type + ctypedef enum grpc_connectivity_state: GRPC_CHANNEL_IDLE GRPC_CHANNEL_CONNECTING @@ -309,6 +323,14 @@ cdef extern from "grpc/grpc.h": void grpc_init() nogil void grpc_shutdown() nogil + ctypedef struct grpc_completion_queue_factory: + pass + + grpc_completion_queue_factory *grpc_completion_queue_factory_lookup( + const grpc_completion_queue_attributes* attributes) nogil + grpc_completion_queue *grpc_completion_queue_create( + const grpc_completion_queue_factory* factory, + const grpc_completion_queue_attributes* attr, void* reserved) nogil grpc_completion_queue *grpc_completion_queue_create_for_next(void *reserved) nogil grpc_event grpc_completion_queue_next(grpc_completion_queue *cq, diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi index 97192efda74..5233edc7895 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi @@ -85,7 +85,7 @@ cdef class Server: def start(self): if self.is_started: raise ValueError("the server has already started") - self.backup_shutdown_queue = CompletionQueue() + self.backup_shutdown_queue = CompletionQueue(shutdown_cq=True) self.register_completion_queue(self.backup_shutdown_queue) self.is_started = True with nogil: diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index d2a570cc87e..42c13b2cb63 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -280,8 +280,10 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create.c', 'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c', + 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c', 'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c', 'third_party/nanopb/pb_common.c', diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py index 17bb3ab616e..1806d311b47 100644 --- a/src/python/grpcio_health_checking/setup.py +++ b/src/python/grpcio_health_checking/setup.py @@ -29,7 +29,6 @@ """Setup module for the GRPC Python package's optional health checking.""" import os -import sys import setuptools diff --git a/templates/binding.gyp.template b/templates/binding.gyp.template index a2e8c588920..933174ab6ed 100644 --- a/templates/binding.gyp.template +++ b/templates/binding.gyp.template @@ -41,15 +41,16 @@ { 'variables': { 'runtime%': 'node', - # UV integration in C core is enabled by default. It can be disabled - # by setting this argument to anything else. - 'grpc_uv%': 'true', # Some Node installations use the system installation of OpenSSL, and on # some systems, the system OpenSSL still does not have ALPN support. This # will let users recompile gRPC to work without ALPN. 'grpc_alpn%': 'true', # Indicates that the library should be built with gcov. - 'grpc_gcov%': 'false' + 'grpc_gcov%': 'false', + # Indicates that the library should be built with compatibility for musl + # libc, so that it can run on Alpine Linux. This is only necessary if not + # building on Alpine Linux + 'grpc_alpine%': 'false' }, 'target_defaults': { 'configurations': { @@ -83,17 +84,11 @@ 'include' ], 'defines': [ - 'GPR_BACKWARDS_COMPATIBILITY_MODE' + 'GPR_BACKWARDS_COMPATIBILITY_MODE', + 'GRPC_ARES=0', + 'GRPC_UV' ], 'conditions': [ - ['grpc_uv=="true"', { - 'defines': [ - 'GRPC_ARES=0', - # Disabling this while bugs are ironed out. Uncomment this to - # re-enable libuv integration in C core. - 'GRPC_UV' - ] - }], ['grpc_gcov=="true"', { % for arg, prop in [('CPPFLAGS', 'cflags'), ('DEFINES', 'defines'), ('LDFLAGS', 'ldflags')]: % if configs['gcov'].get(arg, None) is not None: @@ -105,6 +100,11 @@ % endif % endfor }], + ['grpc_alpine=="true"', { + 'defines': [ + 'GPR_MUSL_LIBC_COMPAT' + ] + }], ['OS!="win" and runtime=="electron"', { "defines": [ 'OPENSSL_NO_THREADS' @@ -233,6 +233,10 @@ } ] }, + ] + }], + ['OS == "win"', { + 'targets': [ # Only want to compile zlib under Windows % for module in node_modules: % for lib in libs: @@ -264,13 +268,6 @@ }] ], 'targets': [ - <% - for lib in libs: - if 'grpc' in lib.transitive_deps or lib.name == 'grpc': - lib.deps.append('node_modules/cares/deps/cares/cares.gyp:cares') - for module in node_modules: - module.deps.append('node_modules/cares/deps/cares/cares.gyp:cares') - %> % for module in node_modules: % for lib in libs: % if lib.name in module.transitive_deps and lib.name not in ('boringssl', 'z'): diff --git a/templates/package.json.template b/templates/package.json.template index b69fd28d2ab..3bae8fde430 100644 --- a/templates/package.json.template +++ b/templates/package.json.template @@ -36,8 +36,7 @@ "lodash": "^4.15.0", "nan": "^2.0.0", "node-pre-gyp": "^0.6.0", - "protobufjs": "^6.7.0", - "cares": "^1.1.5" + "protobufjs": "^6.7.0" }, "devDependencies": { "async": "^2.0.1", diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index 9b0106ec84c..5eea5d43fe0 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -189,23 +189,6 @@ int byte_buffer_eq_string(grpc_byte_buffer *bb, const char *str) { return res; } -static void verify_matches(expectation *e, grpc_event *ev) { - GPR_ASSERT(e->type == ev->type); - switch (e->type) { - case GRPC_QUEUE_SHUTDOWN: - gpr_log(GPR_ERROR, "premature queue shutdown"); - abort(); - break; - case GRPC_OP_COMPLETE: - GPR_ASSERT(e->success == ev->success); - break; - case GRPC_QUEUE_TIMEOUT: - gpr_log(GPR_ERROR, "not implemented"); - abort(); - break; - } -} - static void expectation_to_strvec(gpr_strvec *buf, expectation *e) { char *tmp; @@ -214,7 +197,7 @@ static void expectation_to_strvec(gpr_strvec *buf, expectation *e) { switch (e->type) { case GRPC_OP_COMPLETE: - gpr_asprintf(&tmp, "GRPC_OP_COMPLETE result=%d %s:%d", e->success, + gpr_asprintf(&tmp, "GRPC_OP_COMPLETE success=%d %s:%d", e->success, e->file, e->line); gpr_strvec_add(buf, tmp); break; @@ -248,6 +231,32 @@ static void fail_no_event_received(cq_verifier *v) { abort(); } +static void verify_matches(expectation *e, grpc_event *ev) { + GPR_ASSERT(e->type == ev->type); + switch (e->type) { + case GRPC_OP_COMPLETE: + if (e->success != ev->success) { + gpr_strvec expected; + gpr_strvec_init(&expected); + expectation_to_strvec(&expected, e); + char *s = gpr_strvec_flatten(&expected, NULL); + gpr_strvec_destroy(&expected); + gpr_log(GPR_ERROR, "actual success does not match expected: %s", s); + gpr_free(s); + abort(); + } + break; + case GRPC_QUEUE_SHUTDOWN: + gpr_log(GPR_ERROR, "premature queue shutdown"); + abort(); + break; + case GRPC_QUEUE_TIMEOUT: + gpr_log(GPR_ERROR, "not implemented"); + abort(); + break; + } +} + void cq_verify(cq_verifier *v) { const gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10); while (v->first_expectation != NULL) { diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c index 6a71c20b804..df902a24bff 100644 --- a/test/core/end2end/fake_resolver.c +++ b/test/core/end2end/fake_resolver.c @@ -56,9 +56,6 @@ #include "test/core/end2end/fake_resolver.h" -#define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \ - "grpc.fake_resolver.response_generator" - // // fake_resolver // diff --git a/test/core/end2end/fake_resolver.h b/test/core/end2end/fake_resolver.h index 447289adefa..d9668d0d11b 100644 --- a/test/core/end2end/fake_resolver.h +++ b/test/core/end2end/fake_resolver.h @@ -38,6 +38,9 @@ #include "test/core/util/test_config.h" +#define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \ + "grpc.fake_resolver.response_generator" + void grpc_fake_resolver_init(); // Instances of \a grpc_fake_resolver_response_generator are passed to the diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index 418a54439a9..23b3b2ef3f1 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -50,6 +50,10 @@ TEST_F(CredentialsTest, InvalidGoogleRefreshToken) { EXPECT_EQ(static_cast(nullptr), bad1.get()); } +TEST_F(CredentialsTest, DefaultCredentials) { + auto creds = GoogleDefaultCredentials(); +} + } // namespace testing } // namespace grpc diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index 8e3ae32a494..eb12d371eaf 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -69,6 +69,9 @@ namespace testing { // ServiceA leading comment 1 class ServiceA final { public: + static constexpr char const* service_full_name() { + return "grpc.testing.ServiceA"; + } class StubInterface { public: virtual ~StubInterface() {} @@ -373,6 +376,9 @@ class ServiceA final { // ServiceB leading comment 1 class ServiceB final { public: + static constexpr char const* service_full_name() { + return "grpc.testing.ServiceB"; + } class StubInterface { public: virtual ~StubInterface() {} diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index f1212e15c77..e867493fb9d 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -48,10 +48,10 @@ cc_test( "//:grpc", "//:grpc++", "//external:gtest", + "//src/proto/grpc/health/v1:health_proto", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", - "//src/proto/grpc/health/v1:health_proto", "//test/core/util:gpr_test_util", "//test/core/util:grpc_test_util", "//test/cpp/util:test_util", @@ -198,6 +198,27 @@ cc_test( ], ) + +cc_test( + name = "grpclb_end2end_test", + srcs = ["grpclb_end2end_test.cc"], + deps = [ + ":test_service_impl", + "//:gpr", + "//:grpc", + "//:grpc++", + "//external:gtest", + "//src/proto/grpc/lb/v1:load_balancer_proto", + "//src/proto/grpc/testing:echo_messages_proto", + "//src/proto/grpc/testing:echo_proto", + "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", + "//test/core/end2end:fake_resolver", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + cc_test( name = "proto_server_reflection_test", srcs = ["proto_server_reflection_test.cc"], diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc new file mode 100644 index 00000000000..8417f1a99c8 --- /dev/null +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -0,0 +1,639 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "src/core/lib/iomgr/sockaddr.h" +#include "test/core/end2end/fake_resolver.h" +} + +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" + +#include "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h" +#include "src/proto/grpc/testing/echo.grpc.pb.h" + +// TODO(dgq): Other scenarios in need of testing: +// - Send a serverlist with faulty ip:port addresses (port > 2^16, etc). +// - Test reception of invalid serverlist +// - Test pinging +// - Test against a non-LB server. +// - Random LB server closing the stream unexpectedly. +// - Test using DNS-resolvable names (localhost?) +// - Test handling of creation of faulty RR instance by having the LB return a +// serverlist with non-existent backends after having initially returned a +// valid one. +// +// Findings from end to end testing to be covered here: +// - Handling of LB servers restart, including reconnection after backing-off +// retries. +// - Destruction of load balanced channel (and therefore of grpclb instance) +// while: +// 1) the internal LB call is still active. This should work by virtue +// of the weak reference the LB call holds. The call should be terminated as +// part of the grpclb shutdown process. +// 2) the retry timer is active. Again, the weak reference it holds should +// prevent a premature call to \a glb_destroy. +// - Restart of backend servers with no changes to serverlist. This exercises +// the RR handover mechanism. + +using std::chrono::system_clock; + +using grpc::lb::v1::LoadBalanceResponse; +using grpc::lb::v1::LoadBalanceRequest; +using grpc::lb::v1::LoadBalancer; + +namespace grpc { +namespace testing { +namespace { + +template +class CountedService : public ServiceType { + public: + int request_count() { + std::unique_lock lock(mu_); + return request_count_; + } + + int response_count() { + std::unique_lock lock(mu_); + return response_count_; + } + + void IncreaseResponseCount() { + std::unique_lock lock(mu_); + ++response_count_; + } + void IncreaseRequestCount() { + std::unique_lock lock(mu_); + ++request_count_; + } + + protected: + std::mutex mu_; + + private: + int request_count_ = 0; + int response_count_ = 0; +}; + +using BackendService = CountedService; +using BalancerService = CountedService; + +class BackendServiceImpl : public BackendService { + public: + BackendServiceImpl() {} + + Status Echo(ServerContext* context, const EchoRequest* request, + EchoResponse* response) override { + IncreaseRequestCount(); + const auto status = TestServiceImpl::Echo(context, request, response); + IncreaseResponseCount(); + return status; + } +}; + +grpc::string Ip4ToPackedString(const char* ip_str) { + struct in_addr ip4; + GPR_ASSERT(inet_pton(AF_INET, ip_str, &ip4) == 1); + return grpc::string(reinterpret_cast(&ip4), sizeof(ip4)); +} + +struct ClientStats { + size_t num_calls_started = 0; + size_t num_calls_finished = 0; + size_t num_calls_finished_with_drop_for_rate_limiting = 0; + size_t num_calls_finished_with_drop_for_load_balancing = 0; + size_t num_calls_finished_with_client_failed_to_send = 0; + size_t num_calls_finished_known_received = 0; + + ClientStats& operator+=(const ClientStats& other) { + num_calls_started += other.num_calls_started; + num_calls_finished += other.num_calls_finished; + num_calls_finished_with_drop_for_rate_limiting += + other.num_calls_finished_with_drop_for_rate_limiting; + num_calls_finished_with_drop_for_load_balancing += + other.num_calls_finished_with_drop_for_load_balancing; + num_calls_finished_with_client_failed_to_send += + other.num_calls_finished_with_client_failed_to_send; + num_calls_finished_known_received += + other.num_calls_finished_known_received; + return *this; + } +}; + +class BalancerServiceImpl : public BalancerService { + public: + using Stream = ServerReaderWriter; + using ResponseDelayPair = std::pair; + + explicit BalancerServiceImpl(int client_load_reporting_interval_seconds) + : client_load_reporting_interval_seconds_( + client_load_reporting_interval_seconds), + shutdown_(false) {} + + Status BalanceLoad(ServerContext* context, Stream* stream) override { + LoadBalanceRequest request; + stream->Read(&request); + IncreaseRequestCount(); + gpr_log(GPR_INFO, "LB: recv msg '%s'", request.DebugString().c_str()); + + 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::vector responses_and_delays; + { + std::unique_lock lock(mu_); + responses_and_delays = responses_and_delays_; + } + for (const auto& response_and_delay : responses_and_delays) { + if (shutdown_) break; + SendResponse(stream, response_and_delay.first, response_and_delay.second); + } + + if (client_load_reporting_interval_seconds_ > 0) { + request.Clear(); + stream->Read(&request); + gpr_log(GPR_INFO, "LB: recv client load report msg: '%s'", + request.DebugString().c_str()); + GPR_ASSERT(request.has_client_stats()); + 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_drop_for_rate_limiting += + request.client_stats() + .num_calls_finished_with_drop_for_rate_limiting(); + client_stats_.num_calls_finished_with_drop_for_load_balancing += + request.client_stats() + .num_calls_finished_with_drop_for_load_balancing(); + 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(); + std::lock_guard lock(mu_); + cond_.notify_one(); + } + + return Status::OK; + } + + void add_response(const LoadBalanceResponse& response, int send_after_ms) { + std::unique_lock lock(mu_); + responses_and_delays_.push_back(std::make_pair(response, send_after_ms)); + } + + void Shutdown() { + std::unique_lock lock(mu_); + shutdown_ = true; + } + + static LoadBalanceResponse BuildResponseForBackends( + const std::vector& backend_ports) { + LoadBalanceResponse response; + for (const int backend_port : backend_ports) { + auto* server = response.mutable_server_list()->add_servers(); + server->set_ip_address(Ip4ToPackedString("127.0.0.1")); + server->set_port(backend_port); + } + return response; + } + + const ClientStats& WaitForLoadReport() { + std::unique_lock lock(mu_); + cond_.wait(lock); + return client_stats_; + } + + private: + void SendResponse(Stream* stream, const LoadBalanceResponse& response, + int delay_ms) { + gpr_log(GPR_INFO, "LB: sleeping for %d ms...", delay_ms); + gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(delay_ms, GPR_TIMESPAN))); + gpr_log(GPR_INFO, "LB: Woke up! Sending response '%s'", + response.DebugString().c_str()); + stream->Write(response); + IncreaseResponseCount(); + } + + const int client_load_reporting_interval_seconds_; + std::vector responses_and_delays_; + std::mutex mu_; + std::condition_variable cond_; + ClientStats client_stats_; + bool shutdown_; +}; + +class GrpclbEnd2endTest : public ::testing::Test { + protected: + GrpclbEnd2endTest(int num_backends, int num_balancers, + int client_load_reporting_interval_seconds) + : server_host_("localhost"), + num_backends_(num_backends), + num_balancers_(num_balancers), + client_load_reporting_interval_seconds_( + client_load_reporting_interval_seconds) {} + + void SetUp() override { + response_generator_ = grpc_fake_resolver_response_generator_create(); + // Start the backends. + for (size_t i = 0; i < num_backends_; ++i) { + backends_.emplace_back(new BackendServiceImpl()); + backend_servers_.emplace_back(ServerThread( + "backend", server_host_, backends_.back().get())); + } + // Start the load balancers. + for (size_t i = 0; i < num_balancers_; ++i) { + balancers_.emplace_back( + new BalancerServiceImpl(client_load_reporting_interval_seconds_)); + balancer_servers_.emplace_back(ServerThread( + "balancer", server_host_, balancers_.back().get())); + } + ResetStub(); + std::vector addresses; + for (size_t i = 0; i < balancer_servers_.size(); ++i) { + addresses.emplace_back(AddressData{balancer_servers_[i].port_, true, ""}); + } + SetNextResolution(addresses); + } + + void TearDown() override { + for (size_t i = 0; i < backends_.size(); ++i) { + backend_servers_[i].Shutdown(); + } + for (size_t i = 0; i < balancers_.size(); ++i) { + balancers_[i]->Shutdown(); + balancer_servers_[i].Shutdown(); + } + grpc_fake_resolver_response_generator_unref(response_generator_); + } + + void ResetStub() { + ChannelArguments args; + args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, + response_generator_); + std::ostringstream uri; + uri << "test:///servername_not_used"; + channel_ = + CreateCustomChannel(uri.str(), InsecureChannelCredentials(), args); + stub_ = grpc::testing::EchoTestService::NewStub(channel_); + } + + ClientStats WaitForLoadReports() { + ClientStats client_stats; + for (const auto& balancer : balancers_) { + client_stats += balancer->WaitForLoadReport(); + } + return client_stats; + } + + struct AddressData { + int port; + bool is_balancer; + grpc::string balancer_name; + }; + + void SetNextResolution(const std::vector& address_data) { + grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; + grpc_lb_addresses* addresses = + grpc_lb_addresses_create(address_data.size(), nullptr); + for (size_t i = 0; i < address_data.size(); ++i) { + char* lb_uri_str; + gpr_asprintf(&lb_uri_str, "ipv4:127.0.0.1:%d", address_data[i].port); + grpc_uri* lb_uri = grpc_uri_parse(&exec_ctx, lb_uri_str, true); + GPR_ASSERT(lb_uri != nullptr); + grpc_lb_addresses_set_address_from_uri( + addresses, i, lb_uri, address_data[i].is_balancer, + address_data[i].balancer_name.c_str(), nullptr); + grpc_uri_destroy(lb_uri); + gpr_free(lb_uri_str); + } + grpc_arg fake_addresses = grpc_lb_addresses_create_channel_arg(addresses); + grpc_channel_args fake_result = {1, &fake_addresses}; + grpc_fake_resolver_response_generator_set_response( + &exec_ctx, response_generator_, &fake_result); + grpc_lb_addresses_destroy(&exec_ctx, addresses); + grpc_exec_ctx_finish(&exec_ctx); + } + + const std::vector GetBackendPorts() const { + std::vector backend_ports; + for (const auto& bs : backend_servers_) { + backend_ports.push_back(bs.port_); + } + return backend_ports; + } + + void ScheduleResponseForBalancer(size_t i, + const LoadBalanceResponse& response, + int delay_ms) { + balancers_.at(i)->add_response(response, delay_ms); + } + + std::vector> SendRpc(const string& message, + int num_rpcs, + int timeout_ms = 1000) { + std::vector> results; + EchoRequest request; + EchoResponse response; + request.set_message(message); + for (int i = 0; i < num_rpcs; i++) { + ClientContext context; + context.set_deadline(grpc_timeout_milliseconds_to_deadline(timeout_ms)); + Status status = stub_->Echo(&context, request, &response); + results.push_back(std::make_pair(status, response)); + } + return results; + } + + template + struct ServerThread { + explicit ServerThread(const grpc::string& type, + const grpc::string& server_host, T* service) + : type_(type), service_(service) { + port_ = grpc_pick_unused_port_or_die(); + gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); + std::mutex mu; + std::condition_variable cond; + thread_.reset(new std::thread( + std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); + std::unique_lock lock(mu); + cond.wait(lock); + 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) { + std::ostringstream server_address; + server_address << server_host << ":" << port_; + ServerBuilder builder; + builder.AddListeningPort(server_address.str(), + InsecureServerCredentials()); + builder.RegisterService(service_); + server_ = builder.BuildAndStart(); + std::lock_guard lock(*mu); + cond->notify_one(); + } + + void Shutdown() { + gpr_log(GPR_INFO, "%s about to shutdown", type_.c_str()); + server_->Shutdown(); + thread_->join(); + gpr_log(GPR_INFO, "%s shutdown completed", type_.c_str()); + } + + int port_; + grpc::string type_; + std::unique_ptr server_; + T* service_; + std::unique_ptr thread_; + }; + + const grpc::string kMessage_ = "Live long and prosper."; + const grpc::string server_host_; + const size_t num_backends_; + const size_t num_balancers_; + const int client_load_reporting_interval_seconds_; + std::shared_ptr channel_; + std::unique_ptr stub_; + + std::vector> backends_; + std::vector> balancers_; + + std::vector> backend_servers_; + std::vector> balancer_servers_; + + grpc_fake_resolver_response_generator* response_generator_; +}; + +class SingleBalancerTest : public GrpclbEnd2endTest { + public: + SingleBalancerTest() : GrpclbEnd2endTest(4, 1, 0) {} +}; + +TEST_F(SingleBalancerTest, Vanilla) { + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0); + // Make sure that trying to connect works without a call. + channel_->GetState(true /* try_to_connect */); + // Start servers and send 100 RPCs per server. + const auto& statuses_and_responses = SendRpc(kMessage_, 100 * num_backends_); + + for (const auto& status_and_response : statuses_and_responses) { + EXPECT_TRUE(status_and_response.first.ok()); + EXPECT_EQ(status_and_response.second.message(), kMessage_); + } + + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(100, backend_servers_[i].service_->request_count()); + } + // The balancer got a single request. + EXPECT_EQ(1, balancer_servers_[0].service_->request_count()); + // and sent a single response. + EXPECT_EQ(1, balancer_servers_[0].service_->response_count()); + + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, InitiallyEmptyServerlist) { + const int kServerlistDelayMs = 500 * grpc_test_slowdown_factor(); + const int kCallDeadlineMs = 1000 * grpc_test_slowdown_factor(); + + // First response is an empty serverlist, sent right away. + ScheduleResponseForBalancer(0, LoadBalanceResponse(), 0); + // Send non-empty serverlist only after kServerlistDelayMs + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), + kServerlistDelayMs); + + const auto t0 = system_clock::now(); + // Client will block: LB will initially send empty serverlist. + const auto& statuses_and_responses = + SendRpc(kMessage_, num_backends_, kCallDeadlineMs); + const auto ellapsed_ms = + std::chrono::duration_cast( + system_clock::now() - t0); + // but eventually, the LB sends a serverlist update that allows the call to + // proceed. The call delay must be larger than the delay in sending the + // populated serverlist but under the call's deadline. + EXPECT_GT(ellapsed_ms.count(), kServerlistDelayMs); + EXPECT_LT(ellapsed_ms.count(), kCallDeadlineMs); + + // Each backend should have gotten 1 request. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(1, backend_servers_[i].service_->request_count()); + } + for (const auto& status_and_response : statuses_and_responses) { + EXPECT_TRUE(status_and_response.first.ok()); + EXPECT_EQ(status_and_response.second.message(), kMessage_); + } + + // The balancer got a single request. + EXPECT_EQ(1, balancer_servers_[0].service_->request_count()); + // and sent two responses. + EXPECT_EQ(2, balancer_servers_[0].service_->response_count()); + + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +TEST_F(SingleBalancerTest, RepeatedServerlist) { + constexpr int kServerlistDelayMs = 100; + + // Send a serverlist right away. + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0); + // ... and the same one a bit later. + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), + kServerlistDelayMs); + + // Send num_backends/2 requests. + auto statuses_and_responses = SendRpc(kMessage_, num_backends_ / 2); + // only the first half of the backends will receive them. + for (size_t i = 0; i < backends_.size(); ++i) { + if (i < backends_.size() / 2) + EXPECT_EQ(1, backend_servers_[i].service_->request_count()); + else + EXPECT_EQ(0, backend_servers_[i].service_->request_count()); + } + EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2); + for (const auto& status_and_response : statuses_and_responses) { + EXPECT_TRUE(status_and_response.first.ok()); + EXPECT_EQ(status_and_response.second.message(), kMessage_); + } + + // Wait for the (duplicated) serverlist update. + gpr_sleep_until(gpr_time_add( + gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_millis(kServerlistDelayMs * 1.1, GPR_TIMESPAN))); + + // Verify the LB has sent two responses. + EXPECT_EQ(2, balancer_servers_[0].service_->response_count()); + + // Some more calls to complete the total number of backends. + statuses_and_responses = SendRpc( + kMessage_, + num_backends_ / 2 + (num_backends_ & 0x1) /* extra one if num_bes odd */); + // Because a duplicated serverlist should have no effect, all backends must + // have been hit once now. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(1, backend_servers_[i].service_->request_count()); + } + EXPECT_EQ(statuses_and_responses.size(), num_backends_ / 2); + for (const auto& status_and_response : statuses_and_responses) { + EXPECT_TRUE(status_and_response.first.ok()); + EXPECT_EQ(status_and_response.second.message(), kMessage_); + } + + // The balancer got a single request. + EXPECT_EQ(1, balancer_servers_[0].service_->request_count()); + // Check LB policy name for the channel. + EXPECT_EQ("grpclb", channel_->GetLoadBalancingPolicyName()); +} + +class SingleBalancerWithClientLoadReportingTest : public GrpclbEnd2endTest { + public: + SingleBalancerWithClientLoadReportingTest() : GrpclbEnd2endTest(4, 1, 2) {} +}; + +TEST_F(SingleBalancerWithClientLoadReportingTest, Vanilla) { + ScheduleResponseForBalancer( + 0, BalancerServiceImpl::BuildResponseForBackends(GetBackendPorts()), 0); + // Start servers and send 100 RPCs per server. + const auto& statuses_and_responses = SendRpc(kMessage_, 100 * num_backends_); + + for (const auto& status_and_response : statuses_and_responses) { + EXPECT_TRUE(status_and_response.first.ok()); + EXPECT_EQ(status_and_response.second.message(), kMessage_); + } + + // Each backend should have gotten 100 requests. + for (size_t i = 0; i < backends_.size(); ++i) { + EXPECT_EQ(100, backend_servers_[i].service_->request_count()); + } + // The balancer got a single request. + EXPECT_EQ(1, balancer_servers_[0].service_->request_count()); + // and sent a single response. + EXPECT_EQ(1, balancer_servers_[0].service_->response_count()); + + const ClientStats client_stats = WaitForLoadReports(); + EXPECT_EQ(100 * num_backends_, client_stats.num_calls_started); + EXPECT_EQ(100 * num_backends_, client_stats.num_calls_finished); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_rate_limiting); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_drop_for_load_balancing); + EXPECT_EQ(0U, client_stats.num_calls_finished_with_client_failed_to_send); + EXPECT_EQ(100 * num_backends_, + client_stats.num_calls_finished_known_received); +} + +} // namespace +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc_init(); + grpc_test_init(argc, argv); + grpc_fake_resolver_init(); + ::testing::InitGoogleTest(&argc, argv); + const auto result = RUN_ALL_TESTS(); + grpc_shutdown(); + return result; +} diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc index 041cc0e4c35..b26beb050da 100644 --- a/test/cpp/util/cli_call.cc +++ b/test/cpp/util/cli_call.cc @@ -91,7 +91,7 @@ void CliCall::Write(const grpc::string& request) { void* got_tag; bool ok; - grpc_slice s = grpc_slice_from_copied_string(request.c_str()); + gpr_slice s = gpr_slice_from_copied_buffer(request.data(), request.size()); grpc::Slice req_slice(s, grpc::Slice::STEAL_REF); grpc::ByteBuffer send_buffer(&req_slice, 1); call_->Write(send_buffer, tag(2)); diff --git a/third_party/cares/ares_build.h b/third_party/cares/ares_build.h index 7d69f1e6aec..d6b3d49f37f 100644 --- a/third_party/cares/ares_build.h +++ b/third_party/cares/ares_build.h @@ -251,4 +251,14 @@ typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t; #endif +/* Undefine UNICODE, as c-ares does not use the ANSI version of functions */ +/* explicitly. */ +#ifdef UNICODE +# undef UNICODE +#endif + +#ifdef _UNICODE +# undef _UNICODE +#endif + #endif /* __CARES_BUILD_H */ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index f49c2de76c9..51d77c2b521 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -910,10 +910,14 @@ src/core/ext/filters/client_channel/http_proxy.c \ src/core/ext/filters/client_channel/http_proxy.h \ src/core/ext/filters/client_channel/lb_policy.c \ src/core/ext/filters/client_channel/lb_policy.h \ +src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c \ +src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h \ src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c \ +src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c \ +src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h \ src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \ diff --git a/tools/internal_ci/linux/grpc_fuzzer_api.sh b/tools/internal_ci/linux/grpc_fuzzer_api.sh deleted file mode 100755 index edf884338fc..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_api.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -# change to grpc repo root -cd $(dirname $0)/../../.. - -git submodule update --init - -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -# runtime 23 * 60 mins -config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh api_fuzzer diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.cfg b/tools/internal_ci/linux/grpc_fuzzer_client.cfg deleted file mode 100644 index 1e8f6885763..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_client.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_client.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_fuzzer_client.sh b/tools/internal_ci/linux/grpc_fuzzer_client.sh deleted file mode 100755 index c03f92559c0..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_client.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -# change to grpc repo root -cd $(dirname $0)/../../.. - -git submodule update --init - -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -# runtime 23 * 60 mins -config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh client_fuzzer diff --git a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg deleted file mode 100644 index 72482b62e35..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh b/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh deleted file mode 100755 index 43933e6d82e..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -# change to grpc repo root -cd $(dirname $0)/../../.. - -git submodule update --init - -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -config=asan-trace-cmp tools/jenkins/run_fuzzer.sh hpack_parser_fuzzer_test - diff --git a/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg b/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg deleted file mode 100644 index a4a0e8922e7..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_http_request.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_http_request.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_fuzzer_http_request.sh b/tools/internal_ci/linux/grpc_fuzzer_http_request.sh deleted file mode 100755 index ef975d327a0..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_http_request.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -# change to grpc repo root -cd $(dirname $0)/../../.. - -git submodule update --init - -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -config=asan-trace-cmp tools/jenkins/run_fuzzer.sh http_request_fuzzer_test - diff --git a/tools/internal_ci/linux/grpc_fuzzer_json.cfg b/tools/internal_ci/linux/grpc_fuzzer_json.cfg deleted file mode 100644 index d22da2d7051..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_json.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_json.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg deleted file mode 100644 index cbf44ba29e7..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh b/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh deleted file mode 100755 index 6e7f4b7f291..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -# change to grpc repo root -cd $(dirname $0)/../../.. - -git submodule update --init - -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -config=asan-trace-cmp tools/jenkins/run_fuzzer.sh nanopb_fuzzer_response_test diff --git a/tools/internal_ci/linux/grpc_fuzzer_server.cfg b/tools/internal_ci/linux/grpc_fuzzer_server.cfg deleted file mode 100644 index 7877d517926..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_server.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_server.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_fuzzer_server.sh b/tools/internal_ci/linux/grpc_fuzzer_server.sh deleted file mode 100755 index 82b24b0f20d..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_server.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -set -ex - -# change to grpc repo root -cd $(dirname $0)/../../.. - -git submodule update --init - -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -# runtime 23 * 60 mins -config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh server_fuzzer diff --git a/tools/internal_ci/linux/grpc_fuzzer_uri.cfg b/tools/internal_ci/linux/grpc_fuzzer_uri.cfg deleted file mode 100644 index 134b3d06d61..00000000000 --- a/tools/internal_ci/linux/grpc_fuzzer_uri.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2017, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# Config file for the internal CI (in protobuf text format) - -# Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_uri.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value -action { - define_artifacts { - regex: "git/grpc/fuzzer_output/**" - } -} diff --git a/tools/internal_ci/linux/grpc_master.sh b/tools/internal_ci/linux/grpc_master.sh index 9ecf1239594..bd22dd069c2 100755 --- a/tools/internal_ci/linux/grpc_master.sh +++ b/tools/internal_ci/linux/grpc_master.sh @@ -41,18 +41,10 @@ clang --version || true docker --version || true # Need to increase open files limit for c tests -ulimit -n 2000 +ulimit -n 32768 git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests.py -l c -t -x sponge_log.xml || FAILED="true" - -# kill port_server.py to prevent the build from hanging -ps aux | grep port_server\\.py | awk '{print $2}' | xargs kill -9 - -if [ "$FAILED" != "" ] -then - exit 1 -fi +tools/run_tests/run_tests_matrix.py -f basictests linux --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/grpc_portability.sh b/tools/internal_ci/linux/grpc_portability.sh index 58d3c58e707..6c55ed71cbb 100755 --- a/tools/internal_ci/linux/grpc_portability.sh +++ b/tools/internal_ci/linux/grpc_portability.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f portability linux +tools/run_tests/run_tests_matrix.py -f portability linux --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/grpc_portability_build_only.sh b/tools/internal_ci/linux/grpc_portability_build_only.sh index 80b5c4cb960..787f0302c08 100755 --- a/tools/internal_ci/linux/grpc_portability_build_only.sh +++ b/tools/internal_ci/linux/grpc_portability_build_only.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f portability linux --build_only +tools/run_tests/run_tests_matrix.py -f portability linux --internal_ci --build_only diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh index 335d47af85f..2927ad7de48 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_c_asan.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f c asan +tools/run_tests/run_tests_matrix.py -f c asan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh index fe9565ecbdd..3a3c850a9f2 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_c_msan.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f c msan +tools/run_tests/run_tests_matrix.py -f c msan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh index 49bbbee8594..daebf34521e 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_c_tsan.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f c tsan +tools/run_tests/run_tests_matrix.py -f c tsan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh index 47ccb26f878..29f7fda74b1 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_asan.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f c++ asan +tools/run_tests/run_tests_matrix.py -f c++ asan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh index ee3ec5ebb08..4b9291a4a00 100755 --- a/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh +++ b/tools/internal_ci/linux/sanitizer/grpc_cpp_tsan.sh @@ -37,4 +37,4 @@ git submodule update --init # download docker images from dockerhub export DOCKERHUB_ORGANIZATION=grpctesting -tools/run_tests/run_tests_matrix.py -f c++ tsan +tools/run_tests/run_tests_matrix.py -f c++ tsan --inner_jobs 16 -j 1 --internal_ci diff --git a/tools/internal_ci/linux/grpc_fuzzer_api.cfg b/tools/internal_ci/macos/grpc_master.cfg similarity index 91% rename from tools/internal_ci/linux/grpc_fuzzer_api.cfg rename to tools/internal_ci/macos/grpc_master.cfg index 5c2592e933d..039c99ec42a 100644 --- a/tools/internal_ci/linux/grpc_fuzzer_api.cfg +++ b/tools/internal_ci/macos/grpc_master.cfg @@ -30,10 +30,10 @@ # Config file for the internal CI (in protobuf text format) # Location of the continuous shell script in repository. -build_file: "grpc/tools/internal_ci/linux/grpc_fuzzer_api.sh" -timeout_mins: 1440 # 24 hours is the maximum allowed value +build_file: "grpc/tools/internal_ci/macos/grpc_master.sh" +timeout_mins: 240 action { define_artifacts { - regex: "git/grpc/fuzzer_output/**" + regex: "**/*sponge_log.xml" } } diff --git a/tools/internal_ci/linux/grpc_fuzzer_json.sh b/tools/internal_ci/macos/grpc_master.sh similarity index 86% rename from tools/internal_ci/linux/grpc_fuzzer_json.sh rename to tools/internal_ci/macos/grpc_master.sh index 1e64a026b68..4ce1af73a54 100755 --- a/tools/internal_ci/linux/grpc_fuzzer_json.sh +++ b/tools/internal_ci/macos/grpc_master.sh @@ -35,7 +35,12 @@ cd $(dirname $0)/../../.. git submodule update --init -# download fuzzer docker image from dockerhub -export DOCKERHUB_ORGANIZATION=grpctesting -config=asan-trace-cmp tools/jenkins/run_fuzzer.sh json_fuzzer_test +tools/run_tests/run_tests_matrix.py -f basictests macos --internal_ci || FAILED="true" +# kill port_server.py to prevent the build from hanging +ps aux | grep port_server\\.py | awk '{print $2}' | xargs kill -9 + +if [ "$FAILED" != "" ] +then + exit 1 +fi diff --git a/tools/internal_ci/windows/grpc_master.bat b/tools/internal_ci/windows/grpc_master.bat index 8943390a8de..b6f3c8790f5 100644 --- a/tools/internal_ci/windows/grpc_master.bat +++ b/tools/internal_ci/windows/grpc_master.bat @@ -36,7 +36,7 @@ cd /d %~dp0\..\..\.. git submodule update --init -python tools/run_tests/run_tests_matrix.py -f basictests windows -j 1 --inner_jobs 8 || goto :error +python tools/run_tests/run_tests_matrix.py -f basictests windows -j 1 --inner_jobs 8 --internal_ci || goto :error goto :EOF :error diff --git a/tools/internal_ci/windows/grpc_portability_master.bat b/tools/internal_ci/windows/grpc_portability_master.bat index b98c70146c4..789808664bb 100644 --- a/tools/internal_ci/windows/grpc_portability_master.bat +++ b/tools/internal_ci/windows/grpc_portability_master.bat @@ -36,7 +36,7 @@ cd /d %~dp0\..\..\.. git submodule update --init -python tools/run_tests/run_tests_matrix.py -f portability windows -j 1 --inner_jobs 8 || goto :error +python tools/run_tests/run_tests_matrix.py -f portability windows -j 1 --inner_jobs 8 --internal_ci || goto :error goto :EOF :error diff --git a/tools/run_tests/README.md b/tools/run_tests/README.md index 05d33fd6b1c..60f20747cd0 100644 --- a/tools/run_tests/README.md +++ b/tools/run_tests/README.md @@ -33,7 +33,7 @@ the script also supports orchestrating test runs with client and server running to BigQuery. ###### Example -`tools/run_tests/run_peformance_tests.py -l c++ node` +`tools/run_tests/run_performance_tests.py -l c++ node` ###### Useful options - `--regex` use regex to select particular scenarios to run. diff --git a/tools/run_tests/artifacts/build_artifact_node.sh b/tools/run_tests/artifacts/build_artifact_node.sh index 2da2ac5f919..7a747551e88 100755 --- a/tools/run_tests/artifacts/build_artifact_node.sh +++ b/tools/run_tests/artifacts/build_artifact_node.sh @@ -48,7 +48,7 @@ electron_versions=( 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 ) for version in ${node_versions[@]} do - ./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --target=$version --target_arch=$NODE_TARGET_ARCH + ./node_modules/.bin/node-pre-gyp configure rebuild package testpackage --target=$version --target_arch=$NODE_TARGET_ARCH --grpc_alpine=true cp -r build/stage/* artifacts/ done diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index a5af10e5072..c9628234379 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -3275,6 +3275,29 @@ "third_party": false, "type": "target" }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc++", + "grpc++_test_util", + "grpc_test_util" + ], + "headers": [ + "src/proto/grpc/lb/v1/load_balancer.grpc.pb.h", + "src/proto/grpc/lb/v1/load_balancer.pb.h", + "src/proto/grpc/lb/v1/load_balancer_mock.grpc.pb.h" + ], + "is_filegroup": false, + "language": "c++", + "name": "grpclb_end2end_test", + "src": [ + "test/cpp/end2end/grpclb_end2end_test.cc" + ], + "third_party": false, + "type": "target" + }, { "deps": [ "gpr", @@ -8211,8 +8234,10 @@ "nanopb" ], "headers": [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" ], @@ -8220,10 +8245,14 @@ "language": "c", "name": "grpc_lb_policy_grpclb", "src": [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", @@ -8241,8 +8270,10 @@ "nanopb" ], "headers": [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" ], @@ -8250,10 +8281,14 @@ "language": "c", "name": "grpc_lb_policy_grpclb_secure", "src": [ + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c", + "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c", "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c", diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 17f7c4b454e..e46b0d1d86b 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3395,6 +3395,28 @@ "windows" ] }, + { + "args": [], + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "grpclb_end2end_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ] + }, { "args": [], "ci_platforms": [ diff --git a/tools/run_tests/helper_scripts/build_node.sh b/tools/run_tests/helper_scripts/build_node.sh index 2c4cf02d8fe..07ecf98396a 100755 --- a/tools/run_tests/helper_scripts/build_node.sh +++ b/tools/run_tests/helper_scripts/build_node.sh @@ -46,6 +46,4 @@ case "$CONFIG" in *) config_flag='--release' ;; esac -uv_flag=$2 - -npm install --unsafe-perm --build-from-source $uv_flag $config_flag +npm install --unsafe-perm --build-from-source $config_flag diff --git a/tools/run_tests/helper_scripts/pre_build_cmake.bat b/tools/run_tests/helper_scripts/pre_build_cmake.bat index c937b9e09f8..c721e1624db 100644 --- a/tools/run_tests/helper_scripts/pre_build_cmake.bat +++ b/tools/run_tests/helper_scripts/pre_build_cmake.bat @@ -37,7 +37,10 @@ mkdir build cd build @rem TODO(jtattermusch): Stop hardcoding path to yasm once Jenkins workers can locate yasm correctly -cmake -G "Visual Studio 14 2015" -DgRPC_BUILD_TESTS=ON -DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" ../.. || goto :error +@rem If yasm is not on the path, use hardcoded path instead. +yasm --version || set USE_HARDCODED_YASM_PATH_MAYBE=-DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" + +cmake -G "Visual Studio 14 2015" -DgRPC_BUILD_TESTS=ON %USE_HARDCODED_YASM_PATH_MAYBE% ../.. || goto :error endlocal diff --git a/tools/run_tests/helper_scripts/pre_build_csharp.bat b/tools/run_tests/helper_scripts/pre_build_csharp.bat index e59dac4edce..47ebd8bee3f 100644 --- a/tools/run_tests/helper_scripts/pre_build_csharp.bat +++ b/tools/run_tests/helper_scripts/pre_build_csharp.bat @@ -42,8 +42,12 @@ mkdir build cd build mkdir %ARCHITECTURE% cd %ARCHITECTURE% + @rem TODO(jtattermusch): Stop hardcoding path to yasm once Jenkins workers can locate yasm correctly -cmake -G "Visual Studio 14 2015" -A %ARCHITECTURE% -DgRPC_BUILD_TESTS=OFF -DgRPC_MSVC_STATIC_RUNTIME=ON -DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" ../../.. || goto :error +@rem If yasm is not on the path, use hardcoded path instead. +yasm --version || set USE_HARDCODED_YASM_PATH_MAYBE=-DCMAKE_ASM_NASM_COMPILER="C:/Program Files (x86)/yasm/yasm.exe" + +cmake -G "Visual Studio 14 2015" -A %ARCHITECTURE% -DgRPC_BUILD_TESTS=OFF -DgRPC_MSVC_STATIC_RUNTIME=ON %USE_HARDCODED_YASM_PATH_MAYBE% ../../.. || goto :error cd ..\..\..\src\csharp diff --git a/tools/run_tests/performance/build_performance.sh b/tools/run_tests/performance/build_performance.sh index 3f7c9fed961..5f8749dda27 100755 --- a/tools/run_tests/performance/build_performance.sh +++ b/tools/run_tests/performance/build_performance.sh @@ -61,9 +61,6 @@ do "csharp") python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 --compiler coreclr ;; - "node") - python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 --iomgr_platform=uv - ;; *) python tools/run_tests/run_tests.py -l $language -c $CONFIG --build_only -j 8 ;; diff --git a/tools/run_tests/performance/scenario_config.py b/tools/run_tests/performance/scenario_config.py index ce0808829fd..08411bf9a4e 100644 --- a/tools/run_tests/performance/scenario_config.py +++ b/tools/run_tests/performance/scenario_config.py @@ -409,6 +409,21 @@ class CSharpLanguage: use_generic_payload=True, categories=[SMOKETEST, SCALABLE]) + yield _ping_pong_scenario( + 'csharp_generic_async_streaming_ping_pong_insecure_1MB', rpc_type='STREAMING', + client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', + req_size=1024*1024, resp_size=1024*1024, + use_generic_payload=True, + secure=False, + categories=[SMOKETEST, SCALABLE]) + + yield _ping_pong_scenario( + 'csharp_generic_async_streaming_qps_unconstrained_insecure', rpc_type='STREAMING', + client_type='ASYNC_CLIENT', server_type='ASYNC_GENERIC_SERVER', + unconstrained_client='async', use_generic_payload=True, + secure=False, + categories=[SMOKETEST, SCALABLE]) + yield _ping_pong_scenario( 'csharp_protobuf_async_streaming_ping_pong', rpc_type='STREAMING', client_type='ASYNC_CLIENT', server_type='ASYNC_SERVER') @@ -469,7 +484,6 @@ class CSharpLanguage: req_size=1024*1024, resp_size=1024*1024, categories=[SMOKETEST, SCALABLE]) - def __str__(self): return 'csharp' diff --git a/tools/run_tests/python_utils/port_server.py b/tools/run_tests/python_utils/port_server.py index e96ee0b08c1..079ed70fbf3 100755 --- a/tools/run_tests/python_utils/port_server.py +++ b/tools/run_tests/python_utils/port_server.py @@ -39,6 +39,7 @@ import os import socket import sys import time +import random from SocketServer import ThreadingMixIn import threading @@ -46,7 +47,7 @@ import threading # increment this number whenever making a change to ensure that # the changes are picked up by running CI servers # note that all changes must be backwards compatible -_MY_VERSION = 14 +_MY_VERSION = 19 if len(sys.argv) == 2 and sys.argv[1] == 'dump_version': @@ -72,10 +73,33 @@ pool = [] in_use = {} mu = threading.Lock() +def can_connect(port): + s = socket.socket() + try: + s.connect(('localhost', port)) + return True + except socket.error, e: + return False + finally: + s.close() + +def can_bind(port, proto): + s = socket.socket(proto, socket.SOCK_STREAM) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + try: + s.bind(('localhost', port)) + return True + except socket.error, e: + return False + finally: + s.close() + def refill_pool(max_timeout, req): """Scan for ports not marked for being in use""" - for i in range(1025, 32766): + chk = list(range(1025, 32766)) + random.shuffle(chk) + for i in chk: if len(pool) > 100: break if i in in_use: age = time.time() - in_use[i] @@ -83,16 +107,9 @@ def refill_pool(max_timeout, req): continue req.log_message("kill old request %d" % i) del in_use[i] - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - try: - s.bind(('localhost', i)) + if can_bind(i, socket.AF_INET) and can_bind(i, socket.AF_INET6) and not can_connect(i): req.log_message("found available port %d" % i) pool.append(i) - except: - pass # we really don't care about failures - finally: - s.close() def allocate_port(req): @@ -128,6 +145,7 @@ class Handler(BaseHTTPRequestHandler): def do_GET(self): global keep_running + global mu if self.path == '/get': # allocate a new port, it will stay bound for ten minutes and until # it's unused @@ -142,12 +160,15 @@ class Handler(BaseHTTPRequestHandler): self.send_header('Content-Type', 'text/plain') self.end_headers() p = int(self.path[6:]) + mu.acquire() if p in in_use: del in_use[p] pool.append(p) - self.log_message('drop known port %d' % p) + k = 'known' else: - self.log_message('drop unknown port %d' % p) + k = 'unknown' + mu.release() + self.log_message('drop %s port %d' % (k, p)) elif self.path == '/version_number': # fetch a version string and the current process pid self.send_response(200) @@ -161,8 +182,11 @@ class Handler(BaseHTTPRequestHandler): self.send_response(200) self.send_header('Content-Type', 'text/plain') self.end_headers() + mu.acquire() now = time.time() - self.wfile.write(yaml.dump({'pool': pool, 'in_use': dict((k, now - v) for k, v in in_use.items())})) + out = yaml.dump({'pool': pool, 'in_use': dict((k, now - v) for k, v in in_use.items())}) + mu.release() + self.wfile.write(out) elif self.path == '/quitquitquit': self.send_response(200) self.end_headers() diff --git a/tools/run_tests/python_utils/report_utils.py b/tools/run_tests/python_utils/report_utils.py index 3b2b4f87129..502efc31f4f 100644 --- a/tools/run_tests/python_utils/report_utils.py +++ b/tools/run_tests/python_utils/report_utils.py @@ -64,19 +64,28 @@ def render_junit_xml_report(resultset, xml_report, suite_package='grpc', root = ET.Element('testsuites') testsuite = ET.SubElement(root, 'testsuite', id='1', package=suite_package, name=suite_name) + failure_count = 0 + error_count = 0 for shortname, results in six.iteritems(resultset): for result in results: xml_test = ET.SubElement(testsuite, 'testcase', name=shortname) if result.elapsed_time: xml_test.set('time', str(result.elapsed_time)) - ET.SubElement(xml_test, 'system-out').text = _filter_msg(result.message, - 'XML') + filtered_msg = _filter_msg(result.message, 'XML') if result.state == 'FAILED': - ET.SubElement(xml_test, 'failure', message='Failure') + ET.SubElement(xml_test, 'failure', message='Failure').text = filtered_msg + failure_count += 1 elif result.state == 'TIMEOUT': - ET.SubElement(xml_test, 'error', message='Timeout') + ET.SubElement(xml_test, 'error', message='Timeout').text = filtered_msg + error_count += 1 elif result.state == 'SKIPPED': ET.SubElement(xml_test, 'skipped', message='Skipped') + testsuite.set('failures', str(failure_count)) + testsuite.set('errors', str(error_count)) + # ensure the report directory exists + report_dir = os.path.dirname(os.path.abspath(xml_report)) + if not os.path.exists(report_dir): + os.makedirs(report_dir) tree = ET.ElementTree(root) tree.write(xml_report, encoding='UTF-8') diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 4da2ba4c3b0..62e92c3d1dd 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -430,10 +430,6 @@ class NodeLanguage(object): _check_compiler(self.args.compiler, ['default', 'node0.12', 'node4', 'node5', 'node6', 'node7', 'electron1.3', 'electron1.6']) - if args.iomgr_platform == "uv": - self.use_uv = True - else: - self.use_uv = False if self.args.compiler == 'default': self.runtime = 'node' self.node_version = '7' @@ -481,7 +477,6 @@ class NodeLanguage(object): else: config_flag = '--release' return [['tools\\run_tests\\helper_scripts\\build_node.bat', - '--grpc_uv={}'.format('true' if self.use_uv else 'false'), config_flag]] else: build_script = 'build_node' @@ -490,8 +485,7 @@ class NodeLanguage(object): # building for electron requires a patch version self.node_version += '.0' return [['tools/run_tests/helper_scripts/{}.sh'.format(build_script), - self.node_version, - '--grpc_uv={}'.format('true' if self.use_uv else 'false')]] + self.node_version]] def post_tests_steps(self): return [] diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py index 02f0ec5eff1..474b56b5de5 100755 --- a/tools/run_tests/run_tests_matrix.py +++ b/tools/run_tests/run_tests_matrix.py @@ -55,6 +55,16 @@ _DEFAULT_INNER_JOBS = 2 _REPORT_SUFFIX = 'sponge_log.xml' +def _report_filename(name): + """Generates report file name""" + return 'report_%s_%s' % (name, _REPORT_SUFFIX) + + +def _report_filename_internal_ci(name): + """Generates report file name that leads to better presentation by internal CI""" + return '%s/%s' % (name, _REPORT_SUFFIX) + + def _docker_jobspec(name, runtests_args=[], runtests_envs={}, inner_jobs=_DEFAULT_INNER_JOBS): """Run a single instance of run_tests.py in a docker container""" @@ -63,7 +73,7 @@ def _docker_jobspec(name, runtests_args=[], runtests_envs={}, '--use_docker', '-t', '-j', str(inner_jobs), - '-x', 'report_%s_%s' % (name, _REPORT_SUFFIX), + '-x', _report_filename(name), '--report_suite_name', '%s' % name] + runtests_args, environ=runtests_envs, shortname='run_tests_%s' % name, @@ -83,7 +93,7 @@ def _workspace_jobspec(name, runtests_args=[], workspace_name=None, 'tools/run_tests/helper_scripts/run_tests_in_workspace.sh', '-t', '-j', str(inner_jobs), - '-x', '../report_%s_%s' % (name, _REPORT_SUFFIX), + '-x', '../%s' % _report_filename(name), '--report_suite_name', '%s' % name] + runtests_args, environ=env, shortname='run_tests_%s' % name, @@ -159,7 +169,7 @@ def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS): # sanitizers test_jobs += _generate_jobs(languages=['c'], - configs=['msan', 'asan', 'tsan'], + configs=['msan', 'asan', 'tsan', 'ubsan'], platforms=['linux'], labels=['sanitizers'], extra_args=extra_args, @@ -279,15 +289,6 @@ def _create_portability_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS) platforms=['linux'], arch='default', compiler='electron1.6', - iomgr_platform='uv', - labels=['portability'], - extra_args=extra_args, - inner_jobs=inner_jobs) - - test_jobs += _generate_jobs(languages=['node'], - configs=['dbg'], - platforms=['linux'], - iomgr_platform='uv', labels=['portability'], extra_args=extra_args, inner_jobs=inner_jobs) @@ -380,8 +381,17 @@ if __name__ == "__main__": argp.add_argument('--max_time', default=-1, type=int, help='Maximum amount of time to run tests for' + '(other tests will be skipped)') + argp.add_argument('--internal_ci', + default=False, + action='store_const', + const=True, + help='Put reports into subdirectories to improve presentation of ' + 'results by Internal CI.') args = argp.parse_args() + if args.internal_ci: + _report_filename = _report_filename_internal_ci # override the function + extra_args = [] if args.build_only: extra_args.append('--build_only') @@ -450,7 +460,7 @@ if __name__ == "__main__": ignored_num_skipped_failures, skipped_results = jobset.run( skipped_jobs, skip_jobs=True) resultset.update(skipped_results) - report_utils.render_junit_xml_report(resultset, 'report_%s' % _REPORT_SUFFIX, + report_utils.render_junit_xml_report(resultset, _report_filename('aggregate_tests'), suite_name='aggregate_tests') if num_failures == 0: diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj index 71520098a6d..86b5856d68a 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj @@ -475,8 +475,10 @@ + + @@ -915,10 +917,14 @@ + + + + diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters index de2dfe67e6a..943ad521f75 100644 --- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters +++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters @@ -613,12 +613,18 @@ src\core\ext\transport\chttp2\client\insecure + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb src\core\ext\filters\client_channel\lb_policy\grpclb + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb @@ -1334,12 +1340,18 @@ src\core\ext\transport\chttp2\client + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb src\core\ext\filters\client_channel\lb_policy\grpclb + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj index 0bfda72e815..2db0ffa6920 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj @@ -444,8 +444,10 @@ + + @@ -836,10 +838,14 @@ + + + + diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters index 63c8d7f2542..c7d6670db1b 100644 --- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -547,12 +547,18 @@ src\core\ext\filters\load_reporting + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb src\core\ext\filters\client_channel\lb_policy\grpclb + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb @@ -1181,12 +1187,18 @@ src\core\ext\filters\load_reporting + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb src\core\ext\filters\client_channel\lb_policy\grpclb + + src\core\ext\filters\client_channel\lb_policy\grpclb + src\core\ext\filters\client_channel\lb_policy\grpclb diff --git a/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj b/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj new file mode 100644 index 00000000000..0a10fc60e98 --- /dev/null +++ b/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj @@ -0,0 +1,215 @@ + + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {15BCAA4C-F569-D5B8-50CF-F442CBC71902} + true + $(SolutionDir)IntDir\$(MSBuildProjectName)\ + + + + v100 + + + v110 + + + v120 + + + v140 + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + grpclb_end2end_test + static + Debug + static + Debug + + + grpclb_end2end_test + static + Release + static + Release + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + MultiThreadedDebug + true + None + false + + + Console + true + false + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + NotUsing + Level3 + MaxSpeed + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + true + true + MultiThreaded + true + None + false + + + Console + true + false + true + true + + + + + + + + + + + + + + + + + + {0BE77741-552A-929B-A497-4EF7ECE17A64} + + + {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} + + + {C187A093-A0FE-489D-A40A-6E33DE0F9FEB} + + + {29D16885-7228-4C31-81ED-5F9187C7F2A9} + + + {EAB0A629-17A9-44DB-B5FF-E91A721FE037} + + + {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + diff --git a/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj.filters b/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj.filters new file mode 100644 index 00000000000..7b1ef956e08 --- /dev/null +++ b/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj.filters @@ -0,0 +1,39 @@ + + + + + src\proto\grpc\lb\v1 + + + test\cpp\end2end + + + + + + {5ffc769b-475b-67a1-b131-2af6f6103043} + + + {165c6d96-aac0-d0b0-a1b4-9470159d683e} + + + {0b3a7ccc-ea48-092f-75f1-866995a4ed04} + + + {8f4e5440-acec-c6e3-4a3d-c8ff6ed84e11} + + + {191ccb8f-33fe-b990-20c1-87c04d15a7c2} + + + {f501dace-533d-819c-ca99-9e0359bb67ef} + + + {fcbf6f3b-2707-4605-d76e-f32b545c6531} + + + {f70e20f4-442c-b400-758d-f13abf182438} + + + +