Merge branch 'master' into cq_limited_pollers
diff --git a/.gitmodules b/.gitmodules
index 0f00369..144fd08 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -14,9 +14,6 @@
[submodule "third_party/boringssl"]
path = third_party/boringssl
url = https://github.com/google/boringssl.git
-[submodule "third_party/thrift"]
- path = third_party/thrift
- url = https://github.com/apache/thrift.git
[submodule "third_party/benchmark"]
path = third_party/benchmark
url = https://github.com/google/benchmark
diff --git a/BUILD b/BUILD
index 0339c87..62f0e1d 100644
--- a/BUILD
+++ b/BUILD
@@ -829,14 +829,18 @@
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(
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",
],
@@ -1404,18 +1412,6 @@
)
grpc_cc_library(
- name = "thrift_util",
- language = "c++",
- public_hdrs = [
- "include/grpc++/impl/codegen/thrift_serializer.h",
- "include/grpc++/impl/codegen/thrift_utils.h",
- ],
- deps = [
- "grpc++_codegen_base",
- ],
-)
-
-grpc_cc_library(
name = "grpc++_reflection",
srcs = [
"src/cpp/ext/proto_server_reflection.cc",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a179a0f..f6c5f9e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -676,6 +676,7 @@
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 @@
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 @@
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
@@ -3276,8 +3281,6 @@
include/grpc/impl/codegen/sync_windows.h
include/grpc++/impl/codegen/proto_utils.h
include/grpc++/impl/codegen/config_protobuf.h
- include/grpc++/impl/codegen/thrift_serializer.h
- include/grpc++/impl/codegen/thrift_utils.h
)
string(REPLACE "include/" "" _path ${_hdr})
get_filename_component(_path ${_path} PATH)
@@ -10748,6 +10751,55 @@
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
@@ -11108,6 +11160,7 @@
add_executable(memory_test
test/core/support/memory_test.cc
third_party/googletest/googletest/src/gtest-all.cc
+ third_party/googletest/googlemock/src/gmock-all.cc
)
@@ -11126,6 +11179,8 @@
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}
)
diff --git a/Makefile b/Makefile
index dd35d8c..1a8ee55 100644
--- a/Makefile
+++ b/Makefile
@@ -1154,6 +1154,7 @@
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 @@
$(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 @@
$(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 @@
$(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 @@
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 @@
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 \
@@ -5157,8 +5166,6 @@
include/grpc/impl/codegen/sync_windows.h \
include/grpc++/impl/codegen/proto_utils.h \
include/grpc++/impl/codegen/config_protobuf.h \
- include/grpc++/impl/codegen/thrift_serializer.h \
- include/grpc++/impl/codegen/thrift_utils.h \
LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_SRC))))
@@ -8272,8 +8279,8 @@
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 $@"
@@ -15094,6 +15101,53 @@
$(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 cc02aa1..7f8d3a2 100755
--- a/Rakefile
+++ b/Rakefile
@@ -80,7 +80,7 @@
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/bazel/generate_cc.bzl b/bazel/generate_cc.bzl
index 8f0f94f..d05509f 100644
--- a/bazel/generate_cc.bzl
+++ b/bazel/generate_cc.bzl
@@ -9,18 +9,18 @@
protos = [f for src in ctx.attr.srcs for f in src.proto.direct_sources]
includes = [f for src in ctx.attr.srcs for f in src.proto.transitive_imports]
outs = []
+ # label_len is length of the path from WORKSPACE root to the location of this build file
+ label_len = len(ctx.label.package) + 1
if ctx.executable.plugin:
- outs += [proto.basename[:-len(".proto")] + ".grpc.pb.h" for proto in protos]
- outs += [proto.basename[:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
+ outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.h" for proto in protos]
+ outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
if ctx.attr.generate_mock:
- outs += [proto.basename[:-len(".proto")] + "_mock.grpc.pb.h" for proto in protos]
+ outs += [proto.path[label_len:-len(".proto")] + "_mock.grpc.pb.h" for proto in protos]
else:
- outs += [proto.basename[:-len(".proto")] + ".pb.h" for proto in protos]
- outs += [proto.basename[:-len(".proto")] + ".pb.cc" for proto in protos]
+ outs += [proto.path[label_len:-len(".proto")] + ".pb.h" for proto in protos]
+ outs += [proto.path[label_len:-len(".proto")] + ".pb.cc" for proto in protos]
out_files = [ctx.new_file(out) for out in outs]
- # The following should be replaced with ctx.configuration.buildout
- # whenever this is added to Skylark.
- dir_out = out_files[0].dirname[:-len(protos[0].dirname)]
+ dir_out = str(ctx.genfiles_dir.path)
arguments = []
if ctx.executable.plugin:
diff --git a/binding.gyp b/binding.gyp
index 582c612..c8dd5c1 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 7b60612..b293060 100644
--- a/build.yaml
+++ b/build.yaml
@@ -488,13 +488,17 @@
- 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 @@
- 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
@@ -979,13 +987,6 @@
- include/grpc++/test/server_context_test_spouse.h
deps:
- grpc++
-- name: thrift_util
- language: c++
- public_headers:
- - include/grpc++/impl/codegen/thrift_serializer.h
- - include/grpc++/impl/codegen/thrift_utils.h
- uses:
- - grpc++_codegen_base
libs:
- name: gpr
build: all
@@ -1283,7 +1284,6 @@
- grpc++_codegen_base_src
- grpc++_codegen_proto
- grpc++_config_proto
- - thrift_util
- name: grpc++_unsecure
build: all
language: c++
@@ -3812,6 +3812,20 @@
- 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
@@ -4498,10 +4512,11 @@
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:
@@ -4547,13 +4562,10 @@
- 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 bbd667c..1c0c6d9 100644
--- a/config.m4
+++ b/config.m4
@@ -291,8 +291,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 \
diff --git a/examples/protos/BUILD b/examples/BUILD
similarity index 79%
rename from examples/protos/BUILD
rename to examples/BUILD
index 2ffdf64..382713e 100644
--- a/examples/protos/BUILD
+++ b/examples/BUILD
@@ -33,20 +33,34 @@
grpc_proto_library(
name = "auth_sample",
- srcs = ["auth_sample.proto"],
+ srcs = ["protos/auth_sample.proto"],
)
grpc_proto_library(
name = "hellostreamingworld",
- srcs = ["hellostreamingworld.proto"],
+ srcs = ["protos/hellostreamingworld.proto"],
)
grpc_proto_library(
name = "helloworld",
- srcs = ["helloworld.proto"],
+ srcs = ["protos/helloworld.proto"],
)
grpc_proto_library(
name = "route_guide",
- srcs = ["route_guide.proto"],
+ srcs = ["protos/route_guide.proto"],
+)
+
+cc_binary(
+ name = "greeter_client",
+ srcs = ["cpp/helloworld/greeter_client.cc"],
+ deps = ["helloworld"],
+ defines = ["BAZEL_BUILD"],
+)
+
+cc_binary(
+ name = "greeter_server",
+ srcs = ["cpp/helloworld/greeter_server.cc"],
+ deps = ["helloworld"],
+ defines = ["BAZEL_BUILD"],
)
diff --git a/examples/cpp/helloworld/BUILD b/examples/cpp/helloworld/BUILD
deleted file mode 100644
index b9c3f5d..0000000
--- a/examples/cpp/helloworld/BUILD
+++ /dev/null
@@ -1,42 +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.
-
-cc_binary(
- name = "greeter_client",
- srcs = ["greeter_client.cc"],
- deps = ["//examples/protos:helloworld"],
- defines = ["BAZEL_BUILD"],
-)
-
-cc_binary(
- name = "greeter_server",
- srcs = ["greeter_server.cc"],
- deps = ["//examples/protos:helloworld"],
- defines = ["BAZEL_BUILD"],
-)
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 07755ac..241eba0 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -434,8 +434,10 @@
'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 @@
'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 @@
'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 1cd6d66..b96f3cb 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -350,8 +350,10 @@
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 @@
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 f334ba6..9fe2bbb 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.h
@@ -364,28 +364,6 @@
bool allow_not_getting_message_;
};
-namespace CallOpGenericRecvMessageHelper {
-class DeserializeFunc {
- public:
- virtual Status Deserialize(grpc_byte_buffer* buf) = 0;
- virtual ~DeserializeFunc() {}
-};
-
-template <class R>
-class DeserializeFuncType final : public DeserializeFunc {
- public:
- DeserializeFuncType(R* message) : message_(message) {}
- Status Deserialize(grpc_byte_buffer* buf) override {
- return SerializationTraits<R>::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 @@
template <class R>
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<R>(message);
- deserialize_.reset(func);
+ deserialize_ = [message](grpc_byte_buffer* buf) -> Status {
+ return SerializationTraits<R>::Deserialize(buf, message);
+ };
}
// Do not change status if no message is received.
@@ -420,7 +396,7 @@
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 @@
*status = false;
}
}
- deserialize_.reset();
+ deserialize_ = DeserializeFunc();
}
private:
- std::unique_ptr<CallOpGenericRecvMessageHelper::DeserializeFunc> deserialize_;
+ typedef std::function<Status(grpc_byte_buffer*)> DeserializeFunc;
+ DeserializeFunc deserialize_;
grpc_byte_buffer* recv_buf_;
bool allow_not_getting_message_;
};
diff --git a/include/grpc++/impl/codegen/thrift_serializer.h b/include/grpc++/impl/codegen/thrift_serializer.h
deleted file mode 100644
index 86bc710..0000000
--- a/include/grpc++/impl/codegen/thrift_serializer.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- *
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H
-#define GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H
-
-#include <grpc/impl/codegen/byte_buffer_reader.h>
-#include <grpc/impl/codegen/slice.h>
-#include <thrift/protocol/TBinaryProtocol.h>
-#include <thrift/protocol/TCompactProtocol.h>
-#include <thrift/protocol/TProtocolException.h>
-#include <thrift/transport/TBufferTransports.h>
-#include <thrift/transport/TTransportUtils.h>
-#include <boost/make_shared.hpp>
-#include <memory>
-#include <stdexcept>
-#include <string>
-
-namespace apache {
-namespace thrift {
-namespace util {
-
-using apache::thrift::protocol::TBinaryProtocolT;
-using apache::thrift::protocol::TCompactProtocolT;
-using apache::thrift::protocol::TMessageType;
-using apache::thrift::protocol::TNetworkBigEndian;
-using apache::thrift::transport::TMemoryBuffer;
-using apache::thrift::transport::TBufferBase;
-using apache::thrift::transport::TTransport;
-
-template <typename Dummy, typename Protocol>
-class ThriftSerializer {
- public:
- ThriftSerializer()
- : prepared_(false),
- last_deserialized_(false),
- serialize_version_(false) {}
-
- virtual ~ThriftSerializer() {}
-
- // Serialize the passed type into the internal buffer
- // and returns a pointer to internal buffer and its size
- template <typename T>
- void Serialize(const T& fields, const uint8_t** serialized_buffer,
- size_t* serialized_len) {
- // prepare or reset buffer
- if (!prepared_ || last_deserialized_) {
- prepare();
- } else {
- buffer_->resetBuffer();
- }
- last_deserialized_ = false;
-
- // if required serialize protocol version
- if (serialize_version_) {
- protocol_->writeMessageBegin("", TMessageType(0), 0);
- }
-
- // serialize fields into buffer
- fields.write(protocol_.get());
-
- // write the end of message
- if (serialize_version_) {
- protocol_->writeMessageEnd();
- }
-
- uint8_t* byte_buffer;
- uint32_t byte_buffer_size;
- buffer_->getBuffer(&byte_buffer, &byte_buffer_size);
- *serialized_buffer = byte_buffer;
- *serialized_len = byte_buffer_size;
- }
-
- // Serialize the passed type into the byte buffer
- template <typename T>
- void Serialize(const T& fields, grpc_byte_buffer** bp) {
- const uint8_t* byte_buffer;
- size_t byte_buffer_size;
-
- Serialize(fields, &byte_buffer, &byte_buffer_size);
-
- grpc_slice slice = grpc_slice_from_copied_buffer(
- reinterpret_cast<const char*>(byte_buffer), byte_buffer_size);
-
- *bp = grpc_raw_byte_buffer_create(&slice, 1);
-
- grpc_slice_unref(slice);
- }
-
- // Deserialize the passed char array into the passed type, returns the number
- // of bytes that have been consumed from the passed string.
- template <typename T>
- uint32_t Deserialize(uint8_t* serialized_buffer, size_t length, T* fields) {
- // prepare buffer if necessary
- if (!prepared_) {
- prepare();
- }
- last_deserialized_ = true;
-
- // reset buffer transport
- buffer_->resetBuffer(serialized_buffer, length);
-
- // read the protocol version if necessary
- if (serialize_version_) {
- std::string name = "";
- TMessageType mt = static_cast<TMessageType>(0);
- int32_t seq_id = 0;
- protocol_->readMessageBegin(name, mt, seq_id);
- }
-
- // deserialize buffer into fields
- uint32_t len = fields->read(protocol_.get());
-
- // read the end of message
- if (serialize_version_) {
- protocol_->readMessageEnd();
- }
-
- return len;
- }
-
- // Deserialize the passed byte buffer to passed type, returns the number
- // of bytes consumed from byte buffer
- template <typename T>
- uint32_t Deserialize(grpc_byte_buffer* buffer, T* msg) {
- grpc_byte_buffer_reader reader;
- grpc_byte_buffer_reader_init(&reader, buffer);
-
- grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
-
- uint32_t len =
- Deserialize(GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice), msg);
-
- grpc_slice_unref(slice);
-
- grpc_byte_buffer_reader_destroy(&reader);
-
- return len;
- }
-
- // set serialization version flag
- void SetSerializeVersion(bool value) { serialize_version_ = value; }
-
- // Set the container size limit to deserialize
- // This function should be called after buffer_ is initialized
- void SetContainerSizeLimit(int32_t container_limit) {
- if (!prepared_) {
- prepare();
- }
- protocol_->setContainerSizeLimit(container_limit);
- }
-
- // Set the string size limit to deserialize
- // This function should be called after buffer_ is initialized
- void SetStringSizeLimit(int32_t string_limit) {
- if (!prepared_) {
- prepare();
- }
- protocol_->setStringSizeLimit(string_limit);
- }
-
- private:
- bool prepared_;
- bool last_deserialized_;
- boost::shared_ptr<TMemoryBuffer> buffer_;
- std::shared_ptr<Protocol> protocol_;
- bool serialize_version_;
-
- void prepare() {
- buffer_ = boost::make_shared<TMemoryBuffer>();
- // create a protocol for the memory buffer transport
- protocol_ = std::make_shared<Protocol>(buffer_);
- prepared_ = true;
- }
-
-}; // ThriftSerializer
-
-typedef ThriftSerializer<void, TBinaryProtocolT<TBufferBase, TNetworkBigEndian>>
- ThriftSerializerBinary;
-typedef ThriftSerializer<void, TCompactProtocolT<TBufferBase>>
- ThriftSerializerCompact;
-
-} // namespace util
-} // namespace thrift
-} // namespace apache
-
-#endif // GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H
diff --git a/include/grpc++/impl/codegen/thrift_utils.h b/include/grpc++/impl/codegen/thrift_utils.h
deleted file mode 100644
index 742d739..0000000
--- a/include/grpc++/impl/codegen/thrift_utils.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- *
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
-#define GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
-
-#include <grpc++/impl/codegen/config.h>
-#include <grpc++/impl/codegen/core_codegen_interface.h>
-#include <grpc++/impl/codegen/serialization_traits.h>
-#include <grpc++/impl/codegen/status.h>
-#include <grpc++/impl/codegen/status_code_enum.h>
-#include <grpc++/impl/codegen/thrift_serializer.h>
-#include <grpc/impl/codegen/byte_buffer_reader.h>
-#include <grpc/impl/codegen/slice.h>
-#include <cstdint>
-#include <cstdlib>
-
-namespace grpc {
-
-using apache::thrift::util::ThriftSerializerCompact;
-
-template <class T>
-class SerializationTraits<T, typename std::enable_if<std::is_base_of<
- apache::thrift::TBase, T>::value>::type> {
- public:
- static Status Serialize(const T& msg, grpc_byte_buffer** bp,
- bool* own_buffer) {
- *own_buffer = true;
-
- ThriftSerializerCompact serializer;
- serializer.Serialize(msg, bp);
-
- return Status(StatusCode::OK, "ok");
- }
-
- static Status Deserialize(grpc_byte_buffer* buffer, T* msg,
- int max_receive_message_size) {
- if (!buffer) {
- return Status(StatusCode::INTERNAL, "No payload");
- }
-
- ThriftSerializerCompact deserializer;
- deserializer.Deserialize(buffer, msg);
-
- grpc_byte_buffer_destroy(buffer);
-
- return Status(StatusCode::OK, "ok");
- }
-};
-
-} // namespace grpc
-
-#endif // GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index b2c38b2..4738e02 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -293,6 +293,9 @@
"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 e12f6f4..14e348f 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 <Availability.h>
diff --git a/package.json b/package.json
index 6a01ae2..e1499a0 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 e7d67ec..d47708e 100644
--- a/package.xml
+++ b/package.xml
@@ -359,8 +359,10 @@
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/uri_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/deadline/deadline_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb.h" role="src" />
@@ -593,8 +595,10 @@
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.c" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
<file baseinstalldir="/" name="third_party/nanopb/pb_common.c" role="src" />
diff --git a/setup.py b/setup.py
index 4cbd1a4..18ba802 100644
--- a/setup.py
+++ b/setup.py
@@ -144,6 +144,8 @@
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 @@
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 d3e7162..a1a0258 100644
--- a/src/compiler/cpp_generator.cc
+++ b/src/compiler/cpp_generator.cc
@@ -804,6 +804,12 @@
" 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 50ee54a..278e507 100644
--- a/src/compiler/python_generator.cc
+++ b/src/compiler/python_generator.cc
@@ -622,9 +622,17 @@
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 0463b25..24843d5 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 @@
#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 @@
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 @@
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 @@
.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 @@
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 @@
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 @@
} 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 @@
}
}
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 @@
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 @@
&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 @@
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 @@
}
}
/* 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 @@
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 @@
}
}
/* 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 @@
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 @@
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 2d31499..112ba40 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 @@
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 2542766..184b2ef 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 @@
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 @@
/** \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 @@
\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 @@
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 0000000..67baa46
--- /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 <grpc/support/atm.h>
+#include <grpc/support/log.h>
+
+#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/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h
new file mode 100644
index 0000000..28b313d
--- /dev/null
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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_CLIENT_LOAD_REPORTING_FILTER_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_CLIENT_LOAD_REPORTING_FILTER_H
+
+#include "src/core/lib/channel/channel_stack.h"
+
+extern const grpc_channel_filter grpc_client_load_reporting_filter;
+
+#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 ad5f068..695be4f 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 <errno.h>
-
+#include <limits.h>
#include <string.h>
#include <grpc/byte_buffer_reader.h>
@@ -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 @@
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 @@
* 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 @@
(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 @@
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 @@
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 @@
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 @@
/************************************************************/
/* 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 @@
/** 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
}
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 @@
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 @@
"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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
- }
- }
- /* 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 {
+ 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 empty server list. Picks will stay pending until a "
- "response with > 0 servers is received");
+ "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);
}
- grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
+ /* 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");
}
- } 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_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)) {
+ 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,
+ "Received empty server list. Picks will stay pending until "
+ "a response with > 0 servers is received");
+ }
+ grpc_grpclb_destroy_serverlist(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));
+ }
}
+ 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 @@
}
/* 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 0000000..444c03b
--- /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 <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/useful.h>
+
+#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 0000000..0af4a91
--- /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 <stdbool.h>
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+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 87549b7..81b6932 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 @@
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 @@
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 @@
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 d014b88..0687382 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 <grpc/slice_buffer.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/proto/grpc/lb/v1/load_balancer.pb.h"
#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
@@ -58,6 +59,8 @@
/** 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 @@
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 2b77cd3..b1c5dfc 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 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 ff41e61..4c17f9c 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 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 b2de85c..1af3393 100644
--- a/src/core/ext/filters/client_channel/subchannel.c
+++ b/src/core/ext/filters/client_channel/subchannel.c
@@ -781,7 +781,7 @@
(*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 6473de4..e433c33 100644
--- a/src/core/ext/filters/client_channel/subchannel.h
+++ b/src/core/ext/filters/client_channel/subchannel.h
@@ -119,6 +119,7 @@
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 d4e89d6..67974b0 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 @@
!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 6c931ad..f0a2111 100644
--- a/src/core/lib/channel/context.h
+++ b/src/core/lib/channel/context.h
@@ -50,6 +50,9 @@
/// 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 453a64b..0ac2c2a 100644
--- a/src/core/lib/http/httpcli.c
+++ b/src/core/lib/http/httpcli.c
@@ -105,7 +105,7 @@
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 269dc35..2a553f4 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 1e50f59..b826dde 100644
--- a/src/core/lib/support/cpu_linux.c
+++ b/src/core/lib/support/cpu_linux.c
@@ -67,16 +67,16 @@
}
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 050cc6d..deb8d6b 100644
--- a/src/core/lib/support/wrap_memcpy.c
+++ b/src/core/lib/support/wrap_memcpy.c
@@ -31,6 +31,8 @@
*
*/
+#include <grpc/support/port_platform.h>
+
#include <string.h>
/* 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 b9c0fe6..c9f7c42 100644
--- a/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
@@ -179,6 +179,9 @@
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 b17b2c2..486befe 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -95,10 +95,13 @@
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 8689d18..7ab7734 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServerRunners.cs
@@ -154,6 +154,9 @@
{
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 fe0c80e..49179ab 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 be04cf4..eb6bc0f 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 9b60911..d01abad 100644
--- a/src/node/ext/completion_queue_uv.cc
+++ b/src/node/ext/completion_queue.cc
@@ -31,8 +31,6 @@
*
*/
-#ifdef GRPC_UV
-
#include <grpc/grpc.h>
#include <node.h>
#include <uv.h>
@@ -95,5 +93,3 @@
} // 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 6e54116..0000000
--- 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 <nan.h>
-
-#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<v8::Object> 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 72df5d1..0000000
--- 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 <nan.h>
-#include <node.h>
-
-#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<v8::Object> 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<Object> 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<Object> 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 076f1ed..e193e82 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 @@
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 1871a32..a885a9f 100644
--- a/src/node/ext/server.cc
+++ b/src/node/ext/server.cc
@@ -41,7 +41,6 @@
#include <vector>
#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 @@
Nan::Callback *Server::constructor;
Persistent<FunctionTemplate> Server::fun_tpl;
+static Callback *shutdown_callback = NULL;
+
+class ServerShutdownOp : public Op {
+ public:
+ ServerShutdownOp(grpc_server *server) : server(server) {}
+
+ ~ServerShutdownOp() {}
+
+ Local<Value> GetNodeValue() const { return Nan::Null(); }
+
+ bool ParseOp(Local<Value> 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 @@
server_persist;
};
+Server::Server(grpc_server *server) : wrapped_server(server) {}
+
+Server::~Server() { this->ShutdownServer(); }
+
void Server::Init(Local<Object> exports) {
HandleScope scope;
Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
@@ -177,6 +204,36 @@
}
}
+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<FunctionTemplate> callback_tpl =
+ Nan::New<FunctionTemplate>(ServerShutdownCallback);
+ shutdown_callback =
+ new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked());
+ }
+
+ ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
+ unique_ptr<OpVec> ops(new OpVec());
+ ops->push_back(unique_ptr<Op>(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_generic.cc b/src/node/ext/server_generic.cc
deleted file mode 100644
index 088273d..0000000
--- a/src/node/ext/server_generic.cc
+++ /dev/null
@@ -1,75 +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.
- *
- */
-
-#ifndef GRPC_UV
-
-#include "server.h"
-
-#include <nan.h>
-#include <node.h>
-#include "grpc/grpc.h"
-#include "grpc/support/time.h"
-
-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 */
diff --git a/src/node/ext/server_uv.cc b/src/node/ext/server_uv.cc
deleted file mode 100644
index 709921b..0000000
--- 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 <nan.h>
-#include <node.h>
-#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<Value> GetNodeValue() const { return Nan::Null(); }
-
- bool ParseOp(Local<Value> 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<FunctionTemplate> callback_tpl =
- Nan::New<FunctionTemplate>(ServerShutdownCallback);
- shutdown_callback =
- new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked());
- }
-
- ServerShutdownOp *op = new ServerShutdownOp(this->wrapped_server);
- unique_ptr<OpVec> ops(new OpVec());
- ops->push_back(unique_ptr<Op>(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_nanopb_response.sh b/src/proto/grpc/lb/v1/BUILD
old mode 100755
new mode 100644
similarity index 84%
copy from tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
copy to src/proto/grpc/lb/v1/BUILD
index 6e7f4b7..46d4f2d
--- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.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 nanopb_fuzzer_response_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 34b2623..502b655 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 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 f66f6e4..1db2056 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -217,6 +217,20 @@
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 @@
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 97192ef..5233edc 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 @@
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 d2a570c..42c13b2 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -280,8 +280,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',
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 17bb3ab..1806d31 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 a2e8c58..933174a 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 b69fd28..3bae8fd 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 9b0106e..5eea5d4 100644
--- a/test/core/end2end/cq_verifier.c
+++ b/test/core/end2end/cq_verifier.c
@@ -189,23 +189,6 @@
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 @@
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 @@
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 6a71c20..df902a2 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 447289a..d9668d0 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/core/slice/slice_buffer_test.c b/test/core/slice/slice_buffer_test.c
index bf9ae19..41cff3d 100644
--- a/test/core/slice/slice_buffer_test.c
+++ b/test/core/slice/slice_buffer_test.c
@@ -115,8 +115,8 @@
grpc_slice_buffer_move_first(&src, 2, &dst);
src_len -= 2;
dst_len += 2;
- GPR_ASSERT(src.length == src.length);
- GPR_ASSERT(dst.length == dst.length);
+ GPR_ASSERT(src.length == src_len);
+ GPR_ASSERT(dst.length == dst_len);
}
int main(int argc, char **argv) {
diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc
index 418a544..23b3b2e 100644
--- a/test/cpp/client/credentials_test.cc
+++ b/test/cpp/client/credentials_test.cc
@@ -50,6 +50,10 @@
EXPECT_EQ(static_cast<CallCredentials*>(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 8e3ae32..eb12d37 100644
--- a/test/cpp/codegen/compiler_test_golden
+++ b/test/cpp/codegen/compiler_test_golden
@@ -69,6 +69,9 @@
// 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 @@
// 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 f1212e1..e867493 100644
--- a/test/cpp/end2end/BUILD
+++ b/test/cpp/end2end/BUILD
@@ -48,10 +48,10 @@
"//: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(
+ 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 0000000..8417f1a
--- /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 <memory>
+#include <mutex>
+#include <sstream>
+#include <thread>
+
+#include <grpc++/channel.h>
+#include <grpc++/client_context.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include <gtest/gtest.h>
+
+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 <typename ServiceType>
+class CountedService : public ServiceType {
+ public:
+ int request_count() {
+ std::unique_lock<std::mutex> lock(mu_);
+ return request_count_;
+ }
+
+ int response_count() {
+ std::unique_lock<std::mutex> lock(mu_);
+ return response_count_;
+ }
+
+ void IncreaseResponseCount() {
+ std::unique_lock<std::mutex> lock(mu_);
+ ++response_count_;
+ }
+ void IncreaseRequestCount() {
+ std::unique_lock<std::mutex> lock(mu_);
+ ++request_count_;
+ }
+
+ protected:
+ std::mutex mu_;
+
+ private:
+ int request_count_ = 0;
+ int response_count_ = 0;
+};
+
+using BackendService = CountedService<TestServiceImpl>;
+using BalancerService = CountedService<LoadBalancer::Service>;
+
+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<const char*>(&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<LoadBalanceResponse, LoadBalanceRequest>;
+ using ResponseDelayPair = std::pair<LoadBalanceResponse, int>;
+
+ 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<ResponseDelayPair> responses_and_delays;
+ {
+ std::unique_lock<std::mutex> 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<std::mutex> lock(mu_);
+ cond_.notify_one();
+ }
+
+ return Status::OK;
+ }
+
+ void add_response(const LoadBalanceResponse& response, int send_after_ms) {
+ std::unique_lock<std::mutex> lock(mu_);
+ responses_and_delays_.push_back(std::make_pair(response, send_after_ms));
+ }
+
+ void Shutdown() {
+ std::unique_lock<std::mutex> lock(mu_);
+ shutdown_ = true;
+ }
+
+ static LoadBalanceResponse BuildResponseForBackends(
+ const std::vector<int>& 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<std::mutex> 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<ResponseDelayPair> 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<BackendService>(
+ "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<BalancerService>(
+ "balancer", server_host_, balancers_.back().get()));
+ }
+ ResetStub();
+ std::vector<AddressData> 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<AddressData>& 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<int> GetBackendPorts() const {
+ std::vector<int> 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<std::pair<Status, EchoResponse>> SendRpc(const string& message,
+ int num_rpcs,
+ int timeout_ms = 1000) {
+ std::vector<std::pair<Status, EchoResponse>> 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 <typename T>
+ 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<std::mutex> 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<std::mutex> 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> server_;
+ T* service_;
+ std::unique_ptr<std::thread> 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> channel_;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+
+ std::vector<std::unique_ptr<BackendServiceImpl>> backends_;
+ std::vector<std::unique_ptr<BalancerServiceImpl>> balancers_;
+
+ std::vector<ServerThread<BackendService>> backend_servers_;
+ std::vector<ServerThread<BalancerService>> 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<std::chrono::milliseconds>(
+ 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/thread_manager/thread_manager_test.cc b/test/cpp/thread_manager/thread_manager_test.cc
index 35c8d5d..e1a0366 100644
--- a/test/cpp/thread_manager/thread_manager_test.cc
+++ b/test/cpp/thread_manager/thread_manager_test.cc
@@ -118,7 +118,7 @@
// The number of times DoWork() was called is equal to the number of times
// WORK_FOUND was returned
- gpr_log(GPR_DEBUG, "DoWork() called %ld times",
+ gpr_log(GPR_DEBUG, "DoWork() called %" PRIdPTR " times",
gpr_atm_no_barrier_load(&num_do_work_));
GPR_ASSERT(gpr_atm_no_barrier_load(&num_do_work_) ==
gpr_atm_no_barrier_load(&num_work_found_));
diff --git a/test/cpp/util/cli_call.cc b/test/cpp/util/cli_call.cc
index 041cc0e..b26beb0 100644
--- a/test/cpp/util/cli_call.cc
+++ b/test/cpp/util/cli_call.cc
@@ -91,7 +91,7 @@
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 7d69f1e..d6b3d49 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/third_party/thrift b/third_party/thrift
deleted file mode 160000
index bcad917..0000000
--- a/third_party/thrift
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index f49c2de..51d77c2 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.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.cfg b/tools/internal_ci/linux/grpc_fuzzer_api.cfg
deleted file mode 100644
index 5c2592e..0000000
--- a/tools/internal_ci/linux/grpc_fuzzer_api.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_api.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_api.sh b/tools/internal_ci/linux/grpc_fuzzer_api.sh
deleted file mode 100755
index edf8843..0000000
--- 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.sh b/tools/internal_ci/linux/grpc_fuzzer_client.sh
deleted file mode 100755
index c03f925..0000000
--- 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 72482b6..0000000
--- 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 43933e6..0000000
--- 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 a4a0e89..0000000
--- 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 ef975d3..0000000
--- 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 d22da2d..0000000
--- 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_json.sh b/tools/internal_ci/linux/grpc_fuzzer_json.sh
deleted file mode 100755
index 1e64a02..0000000
--- a/tools/internal_ci/linux/grpc_fuzzer_json.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 json_fuzzer_test
-
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 cbf44ba..0000000
--- 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_server.cfg b/tools/internal_ci/linux/grpc_fuzzer_server.cfg
deleted file mode 100644
index 7877d51..0000000
--- 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 82b24b0..0000000
--- 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 134b3d0..0000000
--- 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_fuzzer_uri.sh b/tools/internal_ci/linux/grpc_fuzzer_uri.sh
deleted file mode 100755
index 67039f3..0000000
--- a/tools/internal_ci/linux/grpc_fuzzer_uri.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 uri_fuzzer_test
diff --git a/tools/internal_ci/linux/grpc_master.sh b/tools/internal_ci/linux/grpc_master.sh
index 9ecf123..bd22dd0 100755
--- a/tools/internal_ci/linux/grpc_master.sh
+++ b/tools/internal_ci/linux/grpc_master.sh
@@ -41,18 +41,10 @@
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 58d3c58..6c55ed7 100755
--- a/tools/internal_ci/linux/grpc_portability.sh
+++ b/tools/internal_ci/linux/grpc_portability.sh
@@ -37,4 +37,4 @@
# 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 80b5c4c..787f030 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 @@
# 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 335d47a..2927ad7 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 @@
# 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 fe9565e..3a3c850 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 @@
# 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 49bbbee..daebf34 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 @@
# 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 47ccb26..29f7fda 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 @@
# 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 ee3ec5e..4b9291a 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 @@
# 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_client.cfg b/tools/internal_ci/macos/grpc_master.cfg
similarity index 90%
rename from tools/internal_ci/linux/grpc_fuzzer_client.cfg
rename to tools/internal_ci/macos/grpc_master.cfg
index 1e8f688..039c99e 100644
--- a/tools/internal_ci/linux/grpc_fuzzer_client.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_client.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_nanopb_response.sh b/tools/internal_ci/macos/grpc_master.sh
similarity index 86%
rename from tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
rename to tools/internal_ci/macos/grpc_master.sh
index 6e7f4b7..4ce1af7 100755
--- a/tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
+++ b/tools/internal_ci/macos/grpc_master.sh
@@ -35,6 +35,12 @@
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
+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 8943390..b6f3c87 100644
--- a/tools/internal_ci/windows/grpc_master.bat
+++ b/tools/internal_ci/windows/grpc_master.bat
@@ -36,7 +36,7 @@
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 b98c701..7898086 100644
--- a/tools/internal_ci/windows/grpc_portability_master.bat
+++ b/tools/internal_ci/windows/grpc_portability_master.bat
@@ -36,7 +36,7 @@
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/jenkins/run_bazel_basic_in_docker.sh b/tools/jenkins/run_bazel_basic_in_docker.sh
index b1d498a..5013f80 100755
--- a/tools/jenkins/run_bazel_basic_in_docker.sh
+++ b/tools/jenkins/run_bazel_basic_in_docker.sh
@@ -39,4 +39,4 @@
&& git submodule update --init --reference /var/local/jenkins/grpc/${name} \
${name}')
cd /var/local/git/grpc
-bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... examples/cpp/...
+bazel build --spawn_strategy=standalone --genrule_strategy=standalone :all test/... examples/...
diff --git a/tools/run_tests/README.md b/tools/run_tests/README.md
index 05d33fd..60f2074 100644
--- a/tools/run_tests/README.md
+++ b/tools/run_tests/README.md
@@ -33,7 +33,7 @@
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 2da2ac5..7a74755 100755
--- a/tools/run_tests/artifacts/build_artifact_node.sh
+++ b/tools/run_tests/artifacts/build_artifact_node.sh
@@ -48,7 +48,7 @@
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 5eba7fb..c962823 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -3291,6 +3291,29 @@
],
"is_filegroup": false,
"language": "c++",
+ "name": "grpclb_end2end_test",
+ "src": [
+ "test/cpp/end2end/grpclb_end2end_test.cc"
+ ],
+ "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_test",
"src": [
"test/cpp/grpclb/grpclb_test.cc"
@@ -6026,8 +6049,7 @@
"grpc++_codegen_base_src",
"grpc++_codegen_proto",
"grpc++_config_proto",
- "grpc_test_util",
- "thrift_util"
+ "grpc_test_util"
],
"headers": [
"src/proto/grpc/health/v1/health.grpc.pb.h",
@@ -8212,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"
],
@@ -8221,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",
@@ -8242,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"
],
@@ -8251,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",
@@ -9129,23 +9163,5 @@
],
"third_party": false,
"type": "filegroup"
- },
- {
- "deps": [
- "grpc++_codegen_base"
- ],
- "headers": [
- "include/grpc++/impl/codegen/thrift_serializer.h",
- "include/grpc++/impl/codegen/thrift_utils.h"
- ],
- "is_filegroup": true,
- "language": "c++",
- "name": "thrift_util",
- "src": [
- "include/grpc++/impl/codegen/thrift_serializer.h",
- "include/grpc++/impl/codegen/thrift_utils.h"
- ],
- "third_party": false,
- "type": "filegroup"
}
]
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 17f7c4b..e46b0d1 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -3407,6 +3407,28 @@
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
+ "gtest": true,
+ "language": "c++",
+ "name": "grpclb_end2end_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "args": [],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
"gtest": false,
"language": "c++",
"name": "grpclb_test",
diff --git a/tools/run_tests/helper_scripts/build_node.sh b/tools/run_tests/helper_scripts/build_node.sh
index 2c4cf02..07ecf98 100755
--- a/tools/run_tests/helper_scripts/build_node.sh
+++ b/tools/run_tests/helper_scripts/build_node.sh
@@ -46,6 +46,4 @@
*) 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 c937b9e..c721e16 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 @@
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 e59dac4..47ebd8b 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 @@
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 3f7c9fe..5f8749d 100755
--- a/tools/run_tests/performance/build_performance.sh
+++ b/tools/run_tests/performance/build_performance.sh
@@ -61,9 +61,6 @@
"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 ce08088..08411bf 100644
--- a/tools/run_tests/performance/scenario_config.py
+++ b/tools/run_tests/performance/scenario_config.py
@@ -410,6 +410,21 @@
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 @@
req_size=1024*1024, resp_size=1024*1024,
categories=[SMOKETEST, SCALABLE])
-
def __str__(self):
return 'csharp'
diff --git a/tools/run_tests/python_utils/jobset.py b/tools/run_tests/python_utils/jobset.py
index 460f359..d01e82a 100755
--- a/tools/run_tests/python_utils/jobset.py
+++ b/tools/run_tests/python_utils/jobset.py
@@ -208,6 +208,11 @@
def __repr__(self):
return 'JobSpec(shortname=%s, cmdline=%s)' % (self.shortname, self.cmdline)
+ def __str__(self):
+ return '%s: %s %s' % (self.shortname,
+ ' '.join('%s=%s' % kv for kv in self.environ.items()),
+ ' '.join(self.cmdline))
+
class JobResult(object):
def __init__(self):
diff --git a/tools/run_tests/python_utils/port_server.py b/tools/run_tests/python_utils/port_server.py
index e96ee0b..079ed70 100755
--- a/tools/run_tests/python_utils/port_server.py
+++ b/tools/run_tests/python_utils/port_server.py
@@ -39,6 +39,7 @@
import socket
import sys
import time
+import random
from SocketServer import ThreadingMixIn
import threading
@@ -46,7 +47,7 @@
# 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 @@
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 @@
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 @@
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 @@
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 @@
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 3b2b4f8..502efc3 100644
--- a/tools/run_tests/python_utils/report_utils.py
+++ b/tools/run_tests/python_utils/report_utils.py
@@ -64,19 +64,28 @@
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_interop_tests.py b/tools/run_tests/run_interop_tests.py
index 44e93eb..867d9e6 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -888,6 +888,10 @@
default=False,
action='store_const',
const=True)
+argp.add_argument('-v', '--verbose',
+ default=False,
+ action='store_const',
+ const=True)
argp.add_argument('--use_docker',
default=False,
action='store_const',
@@ -989,6 +993,9 @@
if build_jobs:
jobset.message('START', 'Building interop docker images.', do_newline=True)
+ if args.verbose:
+ print('Jobs to run: \n%s\n' % '\n'.join(str(j) for j in build_jobs))
+
num_failures, _ = jobset.run(
build_jobs, newline_on_success=True, maxjobs=args.jobs)
if num_failures == 0:
@@ -1164,6 +1171,9 @@
if args.manual_run:
print('All tests will skipped --manual_run option is active.')
+ if args.verbose:
+ print('Jobs to run: \n%s\n' % '\n'.join(str(job) for job in jobs))
+
num_failures, resultset = jobset.run(jobs, newline_on_success=True,
maxjobs=args.jobs,
skip_jobs=args.manual_run)
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 4da2ba4..62e92c3 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -430,10 +430,6 @@
_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 @@
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 @@
# 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 02f0ec5..474b56b 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -55,6 +55,16 @@
_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 @@
'--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 @@
'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 @@
# 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 @@
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 @@
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 @@
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/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 0a9c1cc..6be7a39 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -47,7 +47,6 @@
30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0)
ec44c6c1675c25b9827aacd08c02433cccde7780 third_party/googletest (release-1.8.0)
593e917c176b5bc5aafa57bf9f6030d749d91cd5 third_party/protobuf (v3.1.0-alpha-1-326-g593e917)
- bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c third_party/thrift (bcad917)
cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11)
7691f773af79bf75a62d1863fd0f13ebf9dc51b1 third_party/cares/cares (1.12.0)
EOF
diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
index 165ebe6..4958218 100644
--- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
@@ -197,8 +197,6 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
- <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_serializer.h" />
- <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_utils.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h" />
diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
index d9aa1e3..1e2a2eb 100644
--- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
@@ -186,12 +186,6 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
- <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_serializer.h">
- <Filter>include\grpc++\impl\codegen</Filter>
- </ClInclude>
- <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_utils.h">
- <Filter>include\grpc++\impl\codegen</Filter>
- </ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 7152009..86b5856 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -475,8 +475,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\uri_parser.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\deadline\deadline_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
<ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
@@ -915,10 +917,14 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel_secure.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index de2dfe6..943ad52 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -613,12 +613,18 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\insecure\channel_create_posix.c">
<Filter>src\core\ext\transport\chttp2\client\insecure</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.c">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.c">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel_secure.c">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.c">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.c">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClCompile>
@@ -1334,12 +1340,18 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\transport\chttp2\client\chttp2_connector.h">
<Filter>src\core\ext\transport\chttp2\client</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.h">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.h">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.h">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.h">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.h">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 0bfda72..2db0ffa 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -444,8 +444,10 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_wrapper.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\load_reporting\load_reporting.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\load_reporting\load_reporting_filter.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.h" />
<ClInclude Include="$(SolutionDir)\..\third_party\nanopb\pb.h" />
@@ -836,10 +838,14 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\load_reporting\load_reporting_filter.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.c">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.c">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\proto\grpc\lb\v1\load_balancer.pb.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 63c8d7f..c7d6670 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -547,12 +547,18 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\load_reporting\load_reporting_filter.c">
<Filter>src\core\ext\filters\load_reporting</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.c">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.c">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.c">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.c">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.c">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClCompile>
@@ -1181,12 +1187,18 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\load_reporting\load_reporting_filter.h">
<Filter>src\core\ext\filters\load_reporting</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\client_load_reporting_filter.h">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb.h">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_channel.h">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\grpclb_client_stats.h">
+ <Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\filters\client_channel\lb_policy\grpclb\load_balancer_api.h">
<Filter>src\core\ext\filters\client_channel\lb_policy\grpclb</Filter>
</ClInclude>
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 0000000..0a10fc6
--- /dev/null
+++ b/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{15BCAA4C-F569-D5B8-50CF-F442CBC71902}</ProjectGuid>
+ <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+ <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)\..\vsprojects\cpptest.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>grpclb_end2end_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'">
+ <TargetName>grpclb_end2end_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.grpc.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.grpc.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\grpclb_end2end_test.cc">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+ <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+ <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
+ <Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+ <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+ <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+ <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ </ImportGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+ </Target>
+</Project>
+
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 0000000..7b1ef95
--- /dev/null
+++ b/vsprojects/vcxproj/test/grpclb_end2end_test/grpclb_end2end_test.vcxproj.filters
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\lb\v1\load_balancer.proto">
+ <Filter>src\proto\grpc\lb\v1</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\end2end\grpclb_end2end_test.cc">
+ <Filter>test\cpp\end2end</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="src">
+ <UniqueIdentifier>{5ffc769b-475b-67a1-b131-2af6f6103043}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto">
+ <UniqueIdentifier>{165c6d96-aac0-d0b0-a1b4-9470159d683e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc">
+ <UniqueIdentifier>{0b3a7ccc-ea48-092f-75f1-866995a4ed04}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc\lb">
+ <UniqueIdentifier>{8f4e5440-acec-c6e3-4a3d-c8ff6ed84e11}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc\lb\v1">
+ <UniqueIdentifier>{191ccb8f-33fe-b990-20c1-87c04d15a7c2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test">
+ <UniqueIdentifier>{f501dace-533d-819c-ca99-9e0359bb67ef}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp">
+ <UniqueIdentifier>{fcbf6f3b-2707-4605-d76e-f32b545c6531}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp\end2end">
+ <UniqueIdentifier>{f70e20f4-442c-b400-758d-f13abf182438}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+