Merge branch 'master' into xtra_header

pull/9819/head
yang-g 8 years ago
commit 29a3b28aa2
  1. 3
      .pylintrc
  2. 82
      CMakeLists.txt
  3. 150
      Makefile
  4. 6
      Rakefile
  5. 18
      WORKSPACE
  6. 4
      binding.gyp
  7. 38
      build.yaml
  8. 162
      doc/service_config.md
  9. 2
      examples/ruby/grpc-demo.gemspec
  10. 6
      examples/ruby/without_protobuf/README.md
  11. 49
      examples/ruby/without_protobuf/echo_client.rb
  12. 59
      examples/ruby/without_protobuf/echo_server.rb
  13. 49
      examples/ruby/without_protobuf/echo_services_noprotobuf.rb
  14. 4
      grpc.gemspec
  15. 3
      include/grpc++/impl/codegen/server_context.h
  16. 4
      include/grpc/impl/codegen/port_platform.h
  17. 3
      setup.py
  18. 4
      src/core/ext/census/grpc_filter.c
  19. 33
      src/core/ext/client_channel/client_channel.c
  20. 23
      src/core/ext/client_channel/resolver.c
  21. 31
      src/core/ext/client_channel/resolver.h
  22. 1
      src/core/ext/client_channel/resolver_factory.h
  23. 4
      src/core/ext/client_channel/resolver_registry.c
  24. 3
      src/core/ext/client_channel/resolver_registry.h
  25. 2
      src/core/ext/load_reporting/load_reporting_filter.c
  26. 45
      src/core/ext/resolver/dns/native/dns_resolver.c
  27. 30
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  28. 7
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  29. 15
      src/core/lib/channel/channel_stack.c
  30. 2
      src/core/lib/channel/channel_stack.h
  31. 2
      src/core/lib/channel/compress_filter.c
  32. 2
      src/core/lib/channel/connected_channel.c
  33. 96
      src/core/lib/channel/deadline_filter.c
  34. 12
      src/core/lib/channel/deadline_filter.h
  35. 2
      src/core/lib/channel/http_client_filter.c
  36. 2
      src/core/lib/channel/http_server_filter.c
  37. 2
      src/core/lib/channel/message_size_filter.c
  38. 5
      src/core/lib/iomgr/resolve_address_uv.c
  39. 4
      src/core/lib/iomgr/socket_utils_windows.c
  40. 14
      src/core/lib/iomgr/tcp_client_uv.c
  41. 18
      src/core/lib/iomgr/timer_generic.c
  42. 2
      src/core/lib/iomgr/timer_generic.h
  43. 12
      src/core/lib/iomgr/timer_uv.c
  44. 2
      src/core/lib/iomgr/timer_uv.h
  45. 2
      src/core/lib/security/transport/client_auth_filter.c
  46. 2
      src/core/lib/security/transport/server_auth_filter.c
  47. 141
      src/core/lib/surface/call.c
  48. 2
      src/core/lib/surface/lame_client.c
  49. 4
      src/core/lib/surface/server.c
  50. 4
      src/cpp/common/channel_filter.h
  51. 3
      src/cpp/server/server_cc.cc
  52. 13
      src/cpp/server/server_context.cc
  53. 27
      src/csharp/README.md
  54. 42
      src/node/ext/completion_queue_threadpool.cc
  55. 9
      src/node/src/client.js
  56. 32
      src/node/src/server.js
  57. 107
      src/node/test/surface_test.js
  58. 80
      src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
  59. 9
      src/python/grpcio/grpc/_channel.py
  60. 4
      src/python/grpcio/grpc/_common.py
  61. 15
      src/python/grpcio/grpc/_server.py
  62. 6
      src/python/grpcio_tests/tests/unit/_metadata_test.py
  63. 1
      src/ruby/ext/grpc/extconf.rb
  64. 4
      templates/Makefile.template
  65. 4
      templates/binding.gyp.template
  66. 4
      templates/grpc.gemspec.template
  67. 2
      test/core/channel/channel_stack_test.c
  68. 39
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
  69. 12
      test/core/client_channel/resolvers/dns_resolver_test.c
  70. 15
      test/core/client_channel/resolvers/sockaddr_resolver_test.c
  71. 2
      test/core/end2end/fake_resolver.c
  72. BIN
      test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-5171071900712960
  73. 2
      test/core/end2end/tests/filter_call_init_fails.c
  74. 2
      test/core/end2end/tests/filter_causes_close.c
  75. 2
      test/core/end2end/tests/filter_latency.c
  76. 2
      test/cpp/common/channel_filter_test.cc
  77. 382
      test/cpp/microbenchmarks/bm_call_create.cc
  78. 248
      test/cpp/microbenchmarks/bm_error.cc
  79. 11
      test/cpp/util/BUILD
  80. 2
      third_party/gflags
  81. 169
      third_party/rake-compiler-dock/Dockerfile
  82. 12
      third_party/rake-compiler-dock/build/patches/ruby-2.4.0/no_sendfile.patch
  83. 5
      tools/distrib/build_ruby_environment_macos.sh
  84. 3
      tools/internal_ci/linux/grpc_fuzzer_api.cfg
  85. 4
      tools/internal_ci/linux/grpc_fuzzer_api.sh
  86. 3
      tools/internal_ci/linux/grpc_fuzzer_client.cfg
  87. 2
      tools/internal_ci/linux/grpc_fuzzer_client.sh
  88. 3
      tools/internal_ci/linux/grpc_fuzzer_hpack_parser.cfg
  89. 3
      tools/internal_ci/linux/grpc_fuzzer_hpack_parser.sh
  90. 3
      tools/internal_ci/linux/grpc_fuzzer_http_request.cfg
  91. 3
      tools/internal_ci/linux/grpc_fuzzer_http_request.sh
  92. 3
      tools/internal_ci/linux/grpc_fuzzer_json.cfg
  93. 3
      tools/internal_ci/linux/grpc_fuzzer_json.sh
  94. 3
      tools/internal_ci/linux/grpc_fuzzer_nanopb_response.cfg
  95. 3
      tools/internal_ci/linux/grpc_fuzzer_nanopb_response.sh
  96. 3
      tools/internal_ci/linux/grpc_fuzzer_server.cfg
  97. 4
      tools/internal_ci/linux/grpc_fuzzer_server.sh
  98. 3
      tools/internal_ci/linux/grpc_fuzzer_uri.cfg
  99. 3
      tools/internal_ci/linux/grpc_fuzzer_uri.sh
  100. 3
      tools/internal_ci/linux/grpc_master.cfg
  101. Some files were not shown because too many files have changed in this diff Show More

@ -30,6 +30,5 @@
#TODO: Enable too-many-nested-blocks #TODO: Enable too-many-nested-blocks
#TODO: Enable super-init-not-called #TODO: Enable super-init-not-called
#TODO: Enable no-self-use #TODO: Enable no-self-use
#TODO: Enable no-member
disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use,no-member disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use

@ -567,12 +567,18 @@ add_dependencies(buildtests_cxx alarm_cpp_test)
add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx async_end2end_test)
add_dependencies(buildtests_cxx auth_property_iterator_test) add_dependencies(buildtests_cxx auth_property_iterator_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_call_create)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_closure) add_dependencies(buildtests_cxx bm_closure)
endif() endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_cq) add_dependencies(buildtests_cxx bm_cq)
endif() endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_error)
endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx bm_fullstack) add_dependencies(buildtests_cxx bm_fullstack)
endif() endif()
add_dependencies(buildtests_cxx channel_arguments_test) add_dependencies(buildtests_cxx channel_arguments_test)
@ -7360,6 +7366,44 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_call_create
test/cpp/microbenchmarks/bm_call_create.cc
third_party/googletest/src/gtest-all.cc
)
target_include_directories(bm_call_create
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 ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/include
PRIVATE third_party/googletest
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(bm_call_create
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
benchmark
grpc++_test_util
grpc_test_util
grpc++
grpc
gpr_test_util
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_closure add_executable(bm_closure
test/cpp/microbenchmarks/bm_closure.cc test/cpp/microbenchmarks/bm_closure.cc
third_party/googletest/src/gtest-all.cc third_party/googletest/src/gtest-all.cc
@ -7434,6 +7478,44 @@ endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_error
test/cpp/microbenchmarks/bm_error.cc
third_party/googletest/src/gtest-all.cc
)
target_include_directories(bm_error
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 ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
PRIVATE third_party/googletest/include
PRIVATE third_party/googletest
PRIVATE ${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(bm_error
${_gRPC_PROTOBUF_LIBRARIES}
${_gRPC_ALLTARGETS_LIBRARIES}
benchmark
grpc++_test_util
grpc_test_util
grpc++
grpc
gpr_test_util
gpr
${_gRPC_GFLAGS_LIBRARIES}
)
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(bm_fullstack add_executable(bm_fullstack
test/cpp/microbenchmarks/bm_fullstack.cc test/cpp/microbenchmarks/bm_fullstack.cc
third_party/googletest/src/gtest-all.cc third_party/googletest/src/gtest-all.cc

@ -1040,8 +1040,10 @@ wakeup_fd_cv_test: $(BINDIR)/$(CONFIG)/wakeup_fd_cv_test
alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test alarm_cpp_test: $(BINDIR)/$(CONFIG)/alarm_cpp_test
async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test async_end2end_test: $(BINDIR)/$(CONFIG)/async_end2end_test
auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test auth_property_iterator_test: $(BINDIR)/$(CONFIG)/auth_property_iterator_test
bm_call_create: $(BINDIR)/$(CONFIG)/bm_call_create
bm_closure: $(BINDIR)/$(CONFIG)/bm_closure bm_closure: $(BINDIR)/$(CONFIG)/bm_closure
bm_cq: $(BINDIR)/$(CONFIG)/bm_cq bm_cq: $(BINDIR)/$(CONFIG)/bm_cq
bm_error: $(BINDIR)/$(CONFIG)/bm_error
bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack
channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
@ -1446,8 +1448,10 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_closure \ $(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_cq \ $(BINDIR)/$(CONFIG)/bm_cq \
$(BINDIR)/$(CONFIG)/bm_error \
$(BINDIR)/$(CONFIG)/bm_fullstack \ $(BINDIR)/$(CONFIG)/bm_fullstack \
$(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \
@ -1553,8 +1557,10 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/alarm_cpp_test \ $(BINDIR)/$(CONFIG)/alarm_cpp_test \
$(BINDIR)/$(CONFIG)/async_end2end_test \ $(BINDIR)/$(CONFIG)/async_end2end_test \
$(BINDIR)/$(CONFIG)/auth_property_iterator_test \ $(BINDIR)/$(CONFIG)/auth_property_iterator_test \
$(BINDIR)/$(CONFIG)/bm_call_create \
$(BINDIR)/$(CONFIG)/bm_closure \ $(BINDIR)/$(CONFIG)/bm_closure \
$(BINDIR)/$(CONFIG)/bm_cq \ $(BINDIR)/$(CONFIG)/bm_cq \
$(BINDIR)/$(CONFIG)/bm_error \
$(BINDIR)/$(CONFIG)/bm_fullstack \ $(BINDIR)/$(CONFIG)/bm_fullstack \
$(BINDIR)/$(CONFIG)/channel_arguments_test \ $(BINDIR)/$(CONFIG)/channel_arguments_test \
$(BINDIR)/$(CONFIG)/channel_filter_test \ $(BINDIR)/$(CONFIG)/channel_filter_test \
@ -1871,10 +1877,14 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/async_end2end_test || ( echo test async_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing auth_property_iterator_test" $(E) "[RUN] Testing auth_property_iterator_test"
$(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/auth_property_iterator_test || ( echo test auth_property_iterator_test failed ; exit 1 )
$(E) "[RUN] Testing bm_call_create"
$(Q) $(BINDIR)/$(CONFIG)/bm_call_create || ( echo test bm_call_create failed ; exit 1 )
$(E) "[RUN] Testing bm_closure" $(E) "[RUN] Testing bm_closure"
$(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bm_closure || ( echo test bm_closure failed ; exit 1 )
$(E) "[RUN] Testing bm_cq" $(E) "[RUN] Testing bm_cq"
$(Q) $(BINDIR)/$(CONFIG)/bm_cq || ( echo test bm_cq failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bm_cq || ( echo test bm_cq failed ; exit 1 )
$(E) "[RUN] Testing bm_error"
$(Q) $(BINDIR)/$(CONFIG)/bm_error || ( echo test bm_error failed ; exit 1 )
$(E) "[RUN] Testing bm_fullstack" $(E) "[RUN] Testing bm_fullstack"
$(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 )
$(E) "[RUN] Testing channel_arguments_test" $(E) "[RUN] Testing channel_arguments_test"
@ -2626,15 +2636,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.3 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.3 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBS)
$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.3
$(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so
endif endif
@ -2959,15 +2969,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.3
$(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so
endif endif
@ -3241,15 +3251,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CRONET_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CRONET_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBS)
$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so.3
$(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so $(Q) ln -sf $(SHARED_PREFIX)grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet$(SHARED_VERSION_CORE).so
endif endif
@ -3760,15 +3770,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.3 $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.3
$(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so
endif endif
@ -4035,15 +4045,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc$(SHARED_VERSION_CORE)-dll $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc$(SHARED_VERSION_CORE)-dll
else else
$(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
else else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc
$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so $(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP).so
endif endif
@ -4426,15 +4436,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_cronet$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_cronet$(SHARED_VERSION_CORE)-dll
else else
$(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_CRONET_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_cronet.$(SHARED_EXT_CORE) $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
else else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(LDLIBS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_cronet $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_cronet.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_CRONET_OBJS) $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_cronet
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so $(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP).so
endif endif
@ -4549,15 +4559,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++$(SHARED_VERSION_CPP)-dll $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++$(SHARED_VERSION_CPP)-dll
else else
$(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT_CPP) $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++
else else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgrpc++ $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_reflection.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_REFLECTION_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgrpc++
$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so $(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP).so
endif endif
@ -4905,15 +4915,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr$(SHARED_VERSION_CORE)-dll -lgrpc_unsecure$(SHARED_VERSION_CORE)-dll
else else
$(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP): $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_DEP) $(PROTOBUF_DEP) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT_CORE)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
else else
$(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(LDLIBS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) -lgpr -lgrpc_unsecure $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc++_unsecure.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBGRPC++_UNSECURE_OBJS) $(ZLIB_MERGE_LIBS) $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) -lgpr -lgrpc_unsecure
$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so $(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP).so
endif endif
@ -5446,15 +5456,15 @@ ifeq ($(SYSTEM),MINGW32)
$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(OPENSSL_DEP)
$(E) "[LD] Linking $@" $(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@` $(Q) mkdir -p `dirname $@`
ifeq ($(SYSTEM),Darwin) ifeq ($(SYSTEM),Darwin)
$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
else else
$(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(Q) $(LD) $(LDFLAGS) $(if $(subst Linux,,$(SYSTEM)),,-Wl$(comma)-wrap$(comma)memcpy) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.3 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(ZLIB_MERGE_LIBS) $(LDLIBS)
$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1 $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so.1
$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP).so
endif endif
@ -12292,6 +12302,49 @@ endif
endif endif
BM_CALL_CREATE_SRC = \
test/cpp/microbenchmarks/bm_call_create.cc \
BM_CALL_CREATE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_CALL_CREATE_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_call_create: 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)/bm_call_create: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_call_create: $(PROTOBUF_DEP) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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)/bm_call_create
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_call_create.o: $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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_bm_call_create: $(BM_CALL_CREATE_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_CALL_CREATE_OBJS:.o=.dep)
endif
endif
BM_CLOSURE_SRC = \ BM_CLOSURE_SRC = \
test/cpp/microbenchmarks/bm_closure.cc \ test/cpp/microbenchmarks/bm_closure.cc \
@ -12378,6 +12431,49 @@ endif
endif endif
BM_ERROR_SRC = \
test/cpp/microbenchmarks/bm_error.cc \
BM_ERROR_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_ERROR_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/bm_error: 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)/bm_error: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/bm_error: $(PROTOBUF_DEP) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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)/bm_error
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_error.o: $(LIBDIR)/$(CONFIG)/libbenchmark.a $(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_bm_error: $(BM_ERROR_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(BM_ERROR_OBJS:.o=.dep)
endif
endif
BM_FULLSTACK_SRC = \ BM_FULLSTACK_SRC = \
test/cpp/microbenchmarks/bm_fullstack.cc \ test/cpp/microbenchmarks/bm_fullstack.cc \

@ -93,7 +93,7 @@ task 'dlls' do
[ w64, w32 ].each do |opt| [ w64, w32 ].each do |opt|
env_comp = "CC=#{opt[:cross]}-gcc " env_comp = "CC=#{opt[:cross]}-gcc "
env_comp += "LD=#{opt[:cross]}-gcc " env_comp += "LD=#{opt[:cross]}-gcc "
docker_for_windows "#{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}" docker_for_windows "gem update --system && #{env} #{env_comp} make -j #{out} && #{opt[:cross]}-strip -x -S #{out} && cp #{out} #{opt[:out]}"
end end
end end
@ -107,10 +107,10 @@ task 'gem:native' do
if RUBY_PLATFORM =~ /darwin/ if RUBY_PLATFORM =~ /darwin/
FileUtils.touch 'grpc_c.32.ruby' FileUtils.touch 'grpc_c.32.ruby'
FileUtils.touch 'grpc_c.64.ruby' FileUtils.touch 'grpc_c.64.ruby'
system "rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" system "rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
else else
Rake::Task['dlls'].execute Rake::Task['dlls'].execute
docker_for_windows "bundle && rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}" docker_for_windows "gem update --system && bundle && rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0 V=#{verbose} GRPC_CONFIG=#{grpc_config}"
end end
end end

@ -33,26 +33,36 @@ bind(
actual = "@submodule_gtest//:gtest", actual = "@submodule_gtest//:gtest",
) )
bind(
name = "gflags",
actual = "@com_github_gflags_gflags//:gflags",
)
new_local_repository( new_local_repository(
name = "submodule_boringssl", name = "submodule_boringssl",
path = "third_party/boringssl-with-bazel",
build_file = "third_party/boringssl-with-bazel/BUILD", build_file = "third_party/boringssl-with-bazel/BUILD",
path = "third_party/boringssl-with-bazel",
) )
new_local_repository( new_local_repository(
name = "submodule_zlib", name = "submodule_zlib",
path = "third_party/zlib",
build_file = "third_party/zlib.BUILD", build_file = "third_party/zlib.BUILD",
path = "third_party/zlib",
) )
new_local_repository( new_local_repository(
name = "submodule_protobuf", name = "submodule_protobuf",
path = "third_party/protobuf",
build_file = "third_party/protobuf/BUILD", build_file = "third_party/protobuf/BUILD",
path = "third_party/protobuf",
) )
new_local_repository( new_local_repository(
name = "submodule_gtest", name = "submodule_gtest",
path = "third_party/googletest",
build_file = "third_party/gtest.BUILD", build_file = "third_party/gtest.BUILD",
path = "third_party/googletest",
)
local_repository(
name = "com_github_gflags_gflags",
path = "third_party/gflags",
) )

@ -51,7 +51,9 @@
'conditions': [ 'conditions': [
['runtime=="node"', { ['runtime=="node"', {
'defines': [ 'defines': [
'GRPC_UV' # Disabling this while bugs are ironed out. Uncomment this to
# re-enable libuv integration in C core.
# 'GRPC_UV'
] ]
}], }],
['OS!="win" and runtime=="electron"', { ['OS!="win" and runtime=="electron"', {

@ -2961,6 +2961,25 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: bm_call_create
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_call_create.cc
deps:
- benchmark
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
args:
- --benchmark_min_time=0
platforms:
- mac
- linux
- posix
- name: bm_closure - name: bm_closure
build: test build: test
language: c++ language: c++
@ -2997,6 +3016,25 @@ targets:
- mac - mac
- linux - linux
- posix - posix
- name: bm_error
build: test
language: c++
src:
- test/cpp/microbenchmarks/bm_error.cc
deps:
- benchmark
- grpc++_test_util
- grpc_test_util
- grpc++
- grpc
- gpr_test_util
- gpr
args:
- --benchmark_min_time=0
platforms:
- mac
- linux
- posix
- name: bm_fullstack - name: bm_fullstack
build: test build: test
language: c++ language: c++

@ -12,105 +12,105 @@ The service config is a JSON string of the following form:
``` ```
{ {
# Load balancing policy name. // Load balancing policy name.
# Supported values are 'round_robin' and 'grpclb'. // Supported values are 'round_robin' and 'grpclb'.
# Optional; if unset, the default behavior is pick the first available // Optional; if unset, the default behavior is pick the first available
# backend. // backend.
# Note that if the resolver returns only balancer addresses and no // Note that if the resolver returns only balancer addresses and no
# backend addresses, gRPC will always use the 'grpclb' policy, // backend addresses, gRPC will always use the 'grpclb' policy,
# regardless of what this field is set to. // regardless of what this field is set to.
'loadBalancingPolicy': string, 'loadBalancingPolicy': string,
# Per-method configuration. Optional. // Per-method configuration. Optional.
'methodConfig': [ 'methodConfig': [
{ {
# The names of the methods to which this method config applies. There // The names of the methods to which this method config applies. There
# must be at least one name. Each name entry must be unique across the // must be at least one name. Each name entry must be unique across the
# entire service config. If the 'method' field is empty, then this // entire service config. If the 'method' field is empty, then this
# method config specifies the defaults for all methods for the specified // method config specifies the defaults for all methods for the specified
# service. // service.
# //
# For example, let's say that the service config contains the following // For example, let's say that the service config contains the following
# method config entries: // method config entries:
# //
# 'methodConfig': [ // 'methodConfig': [
# { 'name': [ { 'service': 'MyService' } ] ... }, // { 'name': [ { 'service': 'MyService' } ] ... },
# { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... } // { 'name': [ { 'service': 'MyService', 'method': 'Foo' } ] ... }
# ] // ]
# //
# For a request for MyService/Foo, we will use the second entry, because // For a request for MyService/Foo, we will use the second entry, because
# it exactly matches the service and method name. // it exactly matches the service and method name.
# For a request for MyService/Bar, we will use the first entry, because // For a request for MyService/Bar, we will use the first entry, because
# it provides the default for all methods of MyService. // it provides the default for all methods of MyService.
'name': [ 'name': [
{ {
# RPC service name. Required. // RPC service name. Required.
# If using gRPC with protobuf as the IDL, then this will be of // If using gRPC with protobuf as the IDL, then this will be of
# the form "pkg.service_name", where "pkg" is the package name // the form "pkg.service_name", where "pkg" is the package name
# defined in the proto file. // defined in the proto file.
'service': string, 'service': string,
# RPC method name. Optional (see above). // RPC method name. Optional (see above).
'method': string, 'method': string,
} }
], ],
# Whether RPCs sent to this method should wait until the connection is // Whether RPCs sent to this method should wait until the connection is
# ready by default. If false, the RPC will abort immediately if there // ready by default. If false, the RPC will abort immediately if there
# is a transient failure connecting to the server. Otherwise, gRPC will // is a transient failure connecting to the server. Otherwise, gRPC will
# attempt to connect until the deadline is exceeded. // attempt to connect until the deadline is exceeded.
# //
# The value specified via the gRPC client API will override the value // The value specified via the gRPC client API will override the value
# set here. However, note that setting the value in the client API will // set here. However, note that setting the value in the client API will
# also affect transient errors encountered during name resolution, // also affect transient errors encountered during name resolution,
# which cannot be caught by the value here, since the service config // which cannot be caught by the value here, since the service config
# is obtained by the gRPC client via name resolution. // is obtained by the gRPC client via name resolution.
'waitForReady': bool, 'waitForReady': bool,
# The default timeout in seconds for RPCs sent to this method. This can // The default timeout in seconds for RPCs sent to this method. This can
# be overridden in code. If no reply is received in the specified amount // be overridden in code. If no reply is received in the specified amount
# of time, the request is aborted and a deadline-exceeded error status // of time, the request is aborted and a deadline-exceeded error status
# is returned to the caller. // is returned to the caller.
# //
# The actual deadline used will be the minimum of the value specified // The actual deadline used will be the minimum of the value specified
# here and the value set by the application via the gRPC client API. // here and the value set by the application via the gRPC client API.
# If either one is not set, then the other will be used. // If either one is not set, then the other will be used.
# If neither is set, then the request has no deadline. // If neither is set, then the request has no deadline.
# //
# The format of the value is that of the 'Duration' type defined here: // The format of the value is that of the 'Duration' type defined here:
# https://developers.google.com/protocol-buffers/docs/proto3#json // https://developers.google.com/protocol-buffers/docs/proto3#json
'timeout': string, 'timeout': string,
# The maximum allowed payload size for an individual request or object // The maximum allowed payload size for an individual request or object
# in a stream (client->server) in bytes. The size which is measured is // in a stream (client->server) in bytes. The size which is measured is
# the serialized, uncompressed payload in bytes. This applies both // the serialized, uncompressed payload in bytes. This applies both
# to streaming and non-streaming requests. // to streaming and non-streaming requests.
# //
# The actual value used is the minimum of the value specified here and // The actual value used is the minimum of the value specified here and
# the value set by the application via the gRPC client API. // the value set by the application via the gRPC client API.
# If either one is not set, then the other will be used. // If either one is not set, then the other will be used.
# If neither is set, then the built-in default is used. // If neither is set, then the built-in default is used.
# //
# If a client attempts to send an object larger than this value, it // If a client attempts to send an object larger than this value, it
# will not be sent and the client will see an error. // will not be sent and the client will see an error.
# Note that 0 is a valid value, meaning that the request message must // Note that 0 is a valid value, meaning that the request message must
# be empty. // be empty.
'maxRequestMessageBytes': number, 'maxRequestMessageBytes': number,
# The maximum allowed payload size for an individual response or object // The maximum allowed payload size for an individual response or object
# in a stream (server->client) in bytes. The size which is measured is // in a stream (server->client) in bytes. The size which is measured is
# the serialized, uncompressed payload in bytes. This applies both // the serialized, uncompressed payload in bytes. This applies both
# to streaming and non-streaming requests. // to streaming and non-streaming requests.
# //
# The actual value used is the minimum of the value specified here and // The actual value used is the minimum of the value specified here and
# the value set by the application via the gRPC client API. // the value set by the application via the gRPC client API.
# If either one is not set, then the other will be used. // If either one is not set, then the other will be used.
# If neither is set, then the built-in default is used. // If neither is set, then the built-in default is used.
# //
# If a server attempts to send an object larger than this value, it // If a server attempts to send an object larger than this value, it
# will not be sent, and the client will see an error. // will not be sent, and the client will see an error.
# Note that 0 is a valid value, meaning that the response message must // Note that 0 is a valid value, meaning that the response message must
# be empty. // be empty.
'maxResponseMessageBytes': number 'maxResponseMessageBytes': number
} }
] ]

@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.require_paths = ['lib'] s.require_paths = ['lib']
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
s.add_dependency 'grpc', '~> 1.0.0' s.add_dependency 'grpc', '~> 1.0'
s.add_development_dependency 'bundler', '~> 1.7' s.add_development_dependency 'bundler', '~> 1.7'
end end

@ -0,0 +1,6 @@
gRPC (Ruby) without protobuf
========================
This directory contains a simple example of using gRPC without protobuf.
This is mainly intended to show basic usage of the GRPC::GenericService module

@ -0,0 +1,49 @@
#!/usr/bin/env ruby
# 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.
# Sample app that connects to a 'EchoWithoutProtobuf' service.
#
# Usage: $ path/to/echo_client.rb
this_dir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'grpc'
require 'echo_services_noprotobuf'
def main
stub = EchoWithoutProtobuf::Stub.new('localhost:50051', :this_channel_is_insecure)
user = ARGV.size > 0 ? ARGV[0] : 'world'
message = stub.echo("hello #{user}")
p "Reponse: #{message}"
end
main

@ -0,0 +1,59 @@
#!/usr/bin/env ruby
# 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.
# Sample gRPC server that implements the EchoWithoutProtobuf service.
#
# Usage: $ path/to/echo_server.rb
this_dir = File.expand_path(File.dirname(__FILE__))
$LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir)
require 'grpc'
require 'echo_services_noprotobuf'
# EchoServer is simple server that implements the EchoWithoutProtobuf server.
class EchoServer < EchoWithoutProtobuf::Service
# echo implements the EchoWithoutProtobuf 'Echo' rpc method.
def echo(echo_req, _unused_call)
echo_req
end
end
# main starts an RpcServer that receives requests to EchoWithoutProtobuf at the sample
# server port.
def main
s = GRPC::RpcServer.new
s.add_http2_port('0.0.0.0:50051', :this_port_is_insecure)
s.handle(EchoServer)
s.run_till_terminated
end
main

@ -0,0 +1,49 @@
# Original file comments:
# 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.
#
require 'grpc'
module EchoWithoutProtobuf
# The 'echo without protobuf' service definition.
class Service
include GRPC::GenericService
self.marshal_class_method = :try_convert
self.unmarshal_class_method = :try_convert
self.service_name = 'EchoWithoutProtobuf'
# Request and response are plain strings
rpc :Echo, String, String
end
Stub = Service.rpc_stub_class
end

@ -27,7 +27,7 @@ Gem::Specification.new do |s|
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb ) s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.1.0' s.add_dependency 'google-protobuf', '~> 3.1'
s.add_dependency 'googleauth', '~> 0.5.1' s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'bundler', '~> 1.9'
@ -35,7 +35,7 @@ Gem::Specification.new do |s|
s.add_development_dependency 'logging', '~> 2.0' s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9' s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4' s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9' s.add_development_dependency 'rake-compiler', '~> 1.0'
s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1' s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1'
s.add_development_dependency 'rspec', '~> 3.2' s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0' s.add_development_dependency 'rubocop', '~> 0.30.0'

@ -213,8 +213,7 @@ class ServerContext {
void BeginCompletionOp(Call* call); void BeginCompletionOp(Call* call);
ServerContext(gpr_timespec deadline, grpc_metadata* metadata, ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
size_t metadata_count);
void set_call(grpc_call* call) { call_ = call; } void set_call(grpc_call* call) { call_ = call; }

@ -297,6 +297,10 @@
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#ifdef _PYTHON_MSVC
// The Python 3.5 Windows runtime is missing InetNtop
#define GPR_WIN_INET_NTOP
#endif // _PYTHON_MSVC
#if _MSC_VER < 1700 #if _MSC_VER < 1700
typedef __int8 int8_t; typedef __int8 int8_t;
typedef __int16 int16_t; typedef __int16 int16_t;

@ -105,8 +105,11 @@ if EXTRA_ENV_COMPILE_ARGS is None:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s' EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime32 -D_timeb=__timeb32 -D_ftime_s=_ftime32_s'
else: else:
EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64' EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
elif 'win32' in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -D_PYTHON_MSVC'
elif "linux" in sys.platform or "darwin" in sys.platform: elif "linux" in sys.platform or "darwin" in sys.platform:
EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv' EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv'
if EXTRA_ENV_LINK_ARGS is None: if EXTRA_ENV_LINK_ARGS is None:
EXTRA_ENV_LINK_ARGS = '' EXTRA_ENV_LINK_ARGS = ''
if "linux" in sys.platform or "darwin" in sys.platform: if "linux" in sys.platform or "darwin" in sys.platform:

@ -127,7 +127,7 @@ static void server_start_transport_op(grpc_exec_ctx *exec_ctx,
static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *client_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *d = elem->call_data; call_data *d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d)); memset(d, 0, sizeof(*d));
@ -146,7 +146,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *server_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *d = elem->call_data; call_data *d = elem->call_data;
GPR_ASSERT(d != NULL); GPR_ASSERT(d != NULL);
memset(d, 0, sizeof(*d)); memset(d, 0, sizeof(*d));

@ -230,7 +230,7 @@ static void on_lb_policy_state_changed_locked(grpc_exec_ctx *exec_ctx,
if (w->lb_policy == w->chand->lb_policy) { if (w->lb_policy == w->chand->lb_policy) {
if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) { if (publish_state == GRPC_CHANNEL_SHUTDOWN && w->chand->resolver != NULL) {
publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE; publish_state = GRPC_CHANNEL_TRANSIENT_FAILURE;
grpc_resolver_channel_saw_error(exec_ctx, w->chand->resolver); grpc_resolver_channel_saw_error_locked(exec_ctx, w->chand->resolver);
GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel"); GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
w->chand->lb_policy = NULL; w->chand->lb_policy = NULL;
} }
@ -386,11 +386,12 @@ static void on_resolver_result_changed_locked(grpc_exec_ctx *exec_ctx,
watch_lb_policy(exec_ctx, chand, lb_policy, state); watch_lb_policy(exec_ctx, chand, lb_policy, state);
} }
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result, grpc_resolver_next_locked(exec_ctx, chand->resolver,
&chand->resolver_result,
&chand->on_resolver_result_changed); &chand->on_resolver_result_changed);
} else { } else {
if (chand->resolver != NULL) { if (chand->resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, chand->resolver); grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
} }
@ -451,7 +452,7 @@ static void start_transport_op_locked(grpc_exec_ctx *exec_ctx, void *arg,
set_channel_connectivity_state_locked( set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN, exec_ctx, chand, GRPC_CHANNEL_SHUTDOWN,
GRPC_ERROR_REF(op->disconnect_with_error), "disconnect"); GRPC_ERROR_REF(op->disconnect_with_error), "disconnect");
grpc_resolver_shutdown(exec_ctx, chand->resolver); grpc_resolver_shutdown_locked(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
if (!chand->started_resolving) { if (!chand->started_resolving) {
@ -550,7 +551,7 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
chand->resolver = grpc_resolver_create( chand->resolver = grpc_resolver_create(
exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string, exec_ctx, proxy_name != NULL ? proxy_name : arg->value.string,
new_args != NULL ? new_args : args->channel_args, new_args != NULL ? new_args : args->channel_args,
chand->interested_parties); chand->interested_parties, chand->combiner);
if (proxy_name != NULL) gpr_free(proxy_name); if (proxy_name != NULL) gpr_free(proxy_name);
if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args); if (new_args != NULL) grpc_channel_args_destroy(exec_ctx, new_args);
if (chand->resolver == NULL) { if (chand->resolver == NULL) {
@ -559,13 +560,23 @@ static grpc_error *cc_init_channel_elem(grpc_exec_ctx *exec_ctx,
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
static void shutdown_resolver_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
grpc_resolver *resolver = arg;
grpc_resolver_shutdown_locked(exec_ctx, resolver);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel");
}
/* Destructor for channel_data */ /* Destructor for channel_data */
static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx, static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem) { grpc_channel_element *elem) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
if (chand->resolver != NULL) { if (chand->resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, chand->resolver); grpc_closure_sched(
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); exec_ctx,
grpc_closure_create(shutdown_resolver_locked, chand->resolver,
grpc_combiner_scheduler(chand->combiner, false)),
GRPC_ERROR_NONE);
} }
if (chand->client_channel_factory != NULL) { if (chand->client_channel_factory != NULL) {
grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory); grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
@ -846,7 +857,8 @@ static bool pick_subchannel_locked(
if (chand->resolver != NULL && !chand->started_resolving) { if (chand->resolver != NULL && !chand->started_resolving) {
chand->started_resolving = true; chand->started_resolving = true;
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result, grpc_resolver_next_locked(exec_ctx, chand->resolver,
&chand->resolver_result,
&chand->on_resolver_result_changed); &chand->on_resolver_result_changed);
} }
if (chand->resolver != NULL) { if (chand->resolver != NULL) {
@ -1123,7 +1135,7 @@ static void initial_read_service_config_locked(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
// Initialize data members. // Initialize data members.
@ -1210,7 +1222,8 @@ static void try_to_connect_locked(grpc_exec_ctx *exec_ctx, void *arg,
if (!chand->started_resolving && chand->resolver != NULL) { if (!chand->started_resolving && chand->resolver != NULL) {
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver"); GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
chand->started_resolving = true; chand->started_resolving = true;
grpc_resolver_next(exec_ctx, chand->resolver, &chand->resolver_result, grpc_resolver_next_locked(exec_ctx, chand->resolver,
&chand->resolver_result,
&chand->on_resolver_result_changed); &chand->on_resolver_result_changed);
} }
} }

@ -32,10 +32,13 @@
*/ */
#include "src/core/ext/client_channel/resolver.h" #include "src/core/ext/client_channel/resolver.h"
#include "src/core/lib/iomgr/combiner.h"
void grpc_resolver_init(grpc_resolver *resolver, void grpc_resolver_init(grpc_resolver *resolver,
const grpc_resolver_vtable *vtable) { const grpc_resolver_vtable *vtable,
grpc_combiner *combiner) {
resolver->vtable = vtable; resolver->vtable = vtable;
resolver->combiner = GRPC_COMBINER_REF(combiner, "resolver");
gpr_ref_init(&resolver->refs, 1); gpr_ref_init(&resolver->refs, 1);
} }
@ -62,20 +65,24 @@ void grpc_resolver_unref(grpc_resolver *resolver,
void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
#endif #endif
if (gpr_unref(&resolver->refs)) { if (gpr_unref(&resolver->refs)) {
grpc_combiner *combiner = resolver->combiner;
resolver->vtable->destroy(exec_ctx, resolver); resolver->vtable->destroy(exec_ctx, resolver);
GRPC_COMBINER_UNREF(exec_ctx, combiner, "resolver");
} }
} }
void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
resolver->vtable->shutdown(exec_ctx, resolver); grpc_resolver *resolver) {
resolver->vtable->shutdown_locked(exec_ctx, resolver);
} }
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx, void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) { grpc_resolver *resolver) {
resolver->vtable->channel_saw_error(exec_ctx, resolver); resolver->vtable->channel_saw_error_locked(exec_ctx, resolver);
} }
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_channel_args **result, grpc_closure *on_complete) { grpc_channel_args **result,
resolver->vtable->next(exec_ctx, resolver, result, on_complete); grpc_closure *on_complete) {
resolver->vtable->next_locked(exec_ctx, resolver, result, on_complete);
} }

@ -44,13 +44,15 @@ typedef struct grpc_resolver_vtable grpc_resolver_vtable;
struct grpc_resolver { struct grpc_resolver {
const grpc_resolver_vtable *vtable; const grpc_resolver_vtable *vtable;
gpr_refcount refs; gpr_refcount refs;
grpc_combiner *combiner;
}; };
struct grpc_resolver_vtable { struct grpc_resolver_vtable {
void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*destroy)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*shutdown_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*channel_saw_error_locked)(grpc_exec_ctx *exec_ctx,
void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, grpc_resolver *resolver);
void (*next_locked)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_channel_args **result, grpc_closure *on_complete); grpc_channel_args **result, grpc_closure *on_complete);
}; };
@ -70,21 +72,30 @@ void grpc_resolver_unref(grpc_exec_ctx *exec_ctx, grpc_resolver *policy);
#endif #endif
void grpc_resolver_init(grpc_resolver *resolver, void grpc_resolver_init(grpc_resolver *resolver,
const grpc_resolver_vtable *vtable); const grpc_resolver_vtable *vtable,
grpc_combiner *combiner);
void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void grpc_resolver_shutdown_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver);
/** Notification that the channel has seen an error on some address. /** Notification that the channel has seen an error on some address.
Can be used as a hint that re-resolution is desirable soon. */ Can be used as a hint that re-resolution is desirable soon.
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
Must be called from the combiner passed as a resolver_arg at construction
time.*/
void grpc_resolver_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver); grpc_resolver *resolver);
/** Get the next result from the resolver. Expected to set \a *result with /** Get the next result from the resolver. Expected to set \a *result with
new channel args and then schedule \a on_complete for execution. new channel args and then schedule \a on_complete for execution.
If resolution is fatally broken, set \a *result to NULL and If resolution is fatally broken, set \a *result to NULL and
schedule \a on_complete. */ schedule \a on_complete.
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_channel_args **result, grpc_closure *on_complete); Must be called from the combiner passed as a resolver_arg at construction
time.*/
void grpc_resolver_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_channel_args **result,
grpc_closure *on_complete);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */

@ -50,6 +50,7 @@ typedef struct grpc_resolver_args {
grpc_uri *uri; grpc_uri *uri;
const grpc_channel_args *args; const grpc_channel_args *args;
grpc_pollset_set *pollset_set; grpc_pollset_set *pollset_set;
grpc_combiner *combiner;
} grpc_resolver_args; } grpc_resolver_args;
struct grpc_resolver_factory_vtable { struct grpc_resolver_factory_vtable {

@ -133,7 +133,8 @@ static grpc_resolver_factory *resolve_factory(const char *target,
grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target, grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
const grpc_channel_args *args, const grpc_channel_args *args,
grpc_pollset_set *pollset_set) { grpc_pollset_set *pollset_set,
grpc_combiner *combiner) {
grpc_uri *uri = NULL; grpc_uri *uri = NULL;
char *canonical_target = NULL; char *canonical_target = NULL;
grpc_resolver_factory *factory = grpc_resolver_factory *factory =
@ -144,6 +145,7 @@ grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
resolver_args.uri = uri; resolver_args.uri = uri;
resolver_args.args = args; resolver_args.args = args;
resolver_args.pollset_set = pollset_set; resolver_args.pollset_set = pollset_set;
resolver_args.combiner = combiner;
resolver = resolver =
grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args); grpc_resolver_factory_create_resolver(exec_ctx, factory, &resolver_args);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);

@ -65,7 +65,8 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
should not be NULL. */ should not be NULL. */
grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target, grpc_resolver *grpc_resolver_create(grpc_exec_ctx *exec_ctx, const char *target,
const grpc_channel_args *args, const grpc_channel_args *args,
grpc_pollset_set *pollset_set); grpc_pollset_set *pollset_set,
grpc_combiner *combiner);
/** Find a resolver factory given a name and return an (owned-by-the-caller) /** Find a resolver factory given a name and return an (owned-by-the-caller)
* reference to it */ * reference to it */

@ -100,7 +100,7 @@ static void on_initial_md_ready(grpc_exec_ctx *exec_ctx, void *user_data,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
memset(calld, 0, sizeof(call_data)); memset(calld, 0, sizeof(call_data));

@ -40,6 +40,7 @@
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h" #include "src/core/lib/support/backoff.h"
@ -63,8 +64,6 @@ typedef struct {
/** pollset_set to drive the name resolution process */ /** pollset_set to drive the name resolution process */
grpc_pollset_set *interested_parties; grpc_pollset_set *interested_parties;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** are we currently resolving? */ /** are we currently resolving? */
bool resolving; bool resolving;
/** which version of the result have we published? */ /** which version of the result have we published? */
@ -95,18 +94,20 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r); dns_resolver *r);
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r, grpc_resolver *r);
static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_channel_args **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete); grpc_closure *on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = { static const grpc_resolver_vtable dns_resolver_vtable = {
dns_destroy, dns_shutdown, dns_channel_saw_error, dns_next}; dns_destroy, dns_shutdown_locked, dns_channel_saw_error_locked,
dns_next_locked};
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) { static void dns_shutdown_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver; dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->have_retry_timer) { if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer); grpc_timer_cancel(exec_ctx, &r->retry_timer);
} }
@ -116,25 +117,21 @@ static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
GRPC_ERROR_CREATE("Resolver Shutdown")); GRPC_ERROR_CREATE("Resolver Shutdown"));
r->next_completion = NULL; r->next_completion = NULL;
} }
gpr_mu_unlock(&r->mu);
} }
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, static void dns_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) { grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver; dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (!r->resolving) { if (!r->resolving) {
gpr_backoff_reset(&r->backoff_state); gpr_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(exec_ctx, r); dns_start_resolving_locked(exec_ctx, r);
} }
gpr_mu_unlock(&r->mu);
} }
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, static void dns_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_channel_args **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete) { grpc_closure *on_complete) {
dns_resolver *r = (dns_resolver *)resolver; dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion); GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete; r->next_completion = on_complete;
r->target_result = target_result; r->target_result = target_result;
@ -144,30 +141,26 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
} else { } else {
dns_maybe_finish_next_locked(exec_ctx, r); dns_maybe_finish_next_locked(exec_ctx, r);
} }
gpr_mu_unlock(&r->mu);
} }
static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg, static void dns_on_retry_timer_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
dns_resolver *r = arg; dns_resolver *r = arg;
gpr_mu_lock(&r->mu);
r->have_retry_timer = false; r->have_retry_timer = false;
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
if (!r->resolving) { if (!r->resolving) {
dns_start_resolving_locked(exec_ctx, r); dns_start_resolving_locked(exec_ctx, r);
} }
} }
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer"); GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
} }
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, static void dns_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
dns_resolver *r = arg; dns_resolver *r = arg;
grpc_channel_args *result = NULL; grpc_channel_args *result = NULL;
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving); GPR_ASSERT(r->resolving);
r->resolving = false; r->resolving = false;
if (r->addresses != NULL) { if (r->addresses != NULL) {
@ -198,8 +191,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
} else { } else {
gpr_log(GPR_DEBUG, "retrying immediately"); gpr_log(GPR_DEBUG, "retrying immediately");
} }
grpc_closure_init(&r->on_retry, dns_on_retry_timer, r, grpc_closure_init(&r->on_retry, dns_on_retry_timer_locked, r,
grpc_schedule_on_exec_ctx); grpc_combiner_scheduler(r->base.combiner, false));
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry, now); grpc_timer_init(exec_ctx, &r->retry_timer, next_try, &r->on_retry, now);
} }
if (r->resolved_result != NULL) { if (r->resolved_result != NULL) {
@ -208,7 +201,6 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
r->resolved_result = result; r->resolved_result = result;
r->resolved_version++; r->resolved_version++;
dns_maybe_finish_next_locked(exec_ctx, r); dns_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving"); GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
} }
@ -221,7 +213,8 @@ static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
r->addresses = NULL; r->addresses = NULL;
grpc_resolve_address( grpc_resolve_address(
exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties, exec_ctx, r->name_to_resolve, r->default_port, r->interested_parties,
grpc_closure_create(dns_on_resolved, r, grpc_schedule_on_exec_ctx), grpc_closure_create(dns_on_resolved_locked, r,
grpc_combiner_scheduler(r->base.combiner, false)),
&r->addresses); &r->addresses);
} }
@ -240,7 +233,6 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
dns_resolver *r = (dns_resolver *)gr; dns_resolver *r = (dns_resolver *)gr;
gpr_mu_destroy(&r->mu);
if (r->resolved_result != NULL) { if (r->resolved_result != NULL) {
grpc_channel_args_destroy(exec_ctx, r->resolved_result); grpc_channel_args_destroy(exec_ctx, r->resolved_result);
} }
@ -264,8 +256,7 @@ static grpc_resolver *dns_create(grpc_exec_ctx *exec_ctx,
// Create resolver. // Create resolver.
dns_resolver *r = gpr_malloc(sizeof(dns_resolver)); dns_resolver *r = gpr_malloc(sizeof(dns_resolver));
memset(r, 0, sizeof(*r)); memset(r, 0, sizeof(*r));
gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &dns_resolver_vtable, args->combiner);
grpc_resolver_init(&r->base, &dns_resolver_vtable);
r->name_to_resolve = gpr_strdup(path); r->name_to_resolve = gpr_strdup(path);
r->default_port = gpr_strdup(default_port); r->default_port = gpr_strdup(default_port);
r->channel_args = grpc_channel_args_copy(args->args); r->channel_args = grpc_channel_args_copy(args->args);

@ -45,6 +45,7 @@
#include "src/core/ext/client_channel/parse_address.h" #include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_internal.h"
@ -58,8 +59,6 @@ typedef struct {
grpc_lb_addresses *addresses; grpc_lb_addresses *addresses;
/** channel args */ /** channel args */
grpc_channel_args *channel_args; grpc_channel_args *channel_args;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */ /** have we published? */
bool published; bool published;
/** pending next completion, or NULL */ /** pending next completion, or NULL */
@ -73,48 +72,43 @@ static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r); sockaddr_resolver *r);
static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx, static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *r); grpc_resolver *r);
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r, static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_channel_args **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete); grpc_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = { static const grpc_resolver_vtable sockaddr_resolver_vtable = {
sockaddr_destroy, sockaddr_shutdown, sockaddr_channel_saw_error, sockaddr_destroy, sockaddr_shutdown_locked,
sockaddr_next}; sockaddr_channel_saw_error_locked, sockaddr_next_locked};
static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, static void sockaddr_shutdown_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) { grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver; sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->next_completion != NULL) { if (r->next_completion != NULL) {
*r->target_result = NULL; *r->target_result = NULL;
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL; r->next_completion = NULL;
} }
gpr_mu_unlock(&r->mu);
} }
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx, static void sockaddr_channel_saw_error_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) { grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver; sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
r->published = false; r->published = false;
sockaddr_maybe_finish_next_locked(exec_ctx, r); sockaddr_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
} }
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, static void sockaddr_next_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
grpc_channel_args **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete) { grpc_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver; sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
GPR_ASSERT(!r->next_completion); GPR_ASSERT(!r->next_completion);
r->next_completion = on_complete; r->next_completion = on_complete;
r->target_result = target_result; r->target_result = target_result;
sockaddr_maybe_finish_next_locked(exec_ctx, r); sockaddr_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
} }
static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@ -131,7 +125,6 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr; sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_lb_addresses_destroy(exec_ctx, r->addresses); grpc_lb_addresses_destroy(exec_ctx, r->addresses);
grpc_channel_args_destroy(exec_ctx, r->channel_args); grpc_channel_args_destroy(exec_ctx, r->channel_args);
gpr_free(r); gpr_free(r);
@ -201,8 +194,7 @@ static grpc_resolver *sockaddr_create(grpc_exec_ctx *exec_ctx,
memset(r, 0, sizeof(*r)); memset(r, 0, sizeof(*r));
r->addresses = addresses; r->addresses = addresses;
r->channel_args = grpc_channel_args_copy(args->args); r->channel_args = grpc_channel_args_copy(args->args);
gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable, args->combiner);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
return &r->base; return &r->base;
} }

@ -1114,8 +1114,11 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
grpc_chttp2_list_add_waiting_for_concurrency(t, s); grpc_chttp2_list_add_waiting_for_concurrency(t, s);
maybe_start_some_streams(exec_ctx, t); maybe_start_some_streams(exec_ctx, t);
} else { } else {
grpc_chttp2_cancel_stream(exec_ctx, t, s, grpc_chttp2_cancel_stream(
GRPC_ERROR_CREATE("Transport closed")); exec_ctx, t, s,
grpc_error_set_int(GRPC_ERROR_CREATE("Transport closed"),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_UNAVAILABLE));
} }
} else { } else {
GPR_ASSERT(s->id != 0); GPR_ASSERT(s->id != 0);

@ -173,7 +173,6 @@ grpc_error *grpc_call_stack_init(
grpc_slice path, gpr_timespec start_time, gpr_timespec deadline, grpc_slice path, gpr_timespec start_time, gpr_timespec deadline,
grpc_call_stack *call_stack) { grpc_call_stack *call_stack) {
grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); grpc_channel_element *channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack);
grpc_call_element_args args;
size_t count = channel_stack->count; size_t count = channel_stack->count;
grpc_call_element *call_elems; grpc_call_element *call_elems;
char *user_data; char *user_data;
@ -188,13 +187,15 @@ grpc_error *grpc_call_stack_init(
/* init per-filter data */ /* init per-filter data */
grpc_error *first_error = GRPC_ERROR_NONE; grpc_error *first_error = GRPC_ERROR_NONE;
args.start_time = start_time; const grpc_call_element_args args = {
.start_time = start_time,
.call_stack = call_stack,
.server_transport_data = transport_server_data,
.context = context,
.path = path,
.deadline = deadline,
};
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
args.call_stack = call_stack;
args.server_transport_data = transport_server_data;
args.context = context;
args.path = path;
args.deadline = deadline;
call_elems[i].filter = channel_elems[i].filter; call_elems[i].filter = channel_elems[i].filter;
call_elems[i].channel_data = channel_elems[i].channel_data; call_elems[i].channel_data = channel_elems[i].channel_data;
call_elems[i].call_data = user_data; call_elems[i].call_data = user_data;

@ -131,7 +131,7 @@ typedef struct {
argument. */ argument. */
grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx, grpc_error *(*init_call_elem)(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args); const grpc_call_element_args *args);
void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx, void (*set_pollset_or_pollset_set)(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_polling_entity *pollent); grpc_polling_entity *pollent);

@ -274,7 +274,7 @@ static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;

@ -83,7 +83,7 @@ static void con_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
int r = grpc_transport_init_stream( int r = grpc_transport_init_stream(

@ -52,9 +52,6 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
grpc_error* error) { grpc_error* error) {
grpc_call_element* elem = arg; grpc_call_element* elem = arg;
grpc_deadline_state* deadline_state = elem->call_data; grpc_deadline_state* deadline_state = elem->call_data;
gpr_mu_lock(&deadline_state->timer_mu);
deadline_state->timer_pending = false;
gpr_mu_unlock(&deadline_state->timer_mu);
if (error != GRPC_ERROR_CANCELLED) { if (error != GRPC_ERROR_CANCELLED) {
grpc_call_element_signal_error( grpc_call_element_signal_error(
exec_ctx, elem, exec_ctx, elem,
@ -66,62 +63,73 @@ static void timer_callback(grpc_exec_ctx* exec_ctx, void* arg,
} }
// Starts the deadline timer. // Starts the deadline timer.
static void start_timer_if_needed_locked(grpc_exec_ctx* exec_ctx, static void start_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem, grpc_call_element* elem,
gpr_timespec deadline) { gpr_timespec deadline) {
grpc_deadline_state* deadline_state = elem->call_data;
deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC); deadline = gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC);
if (gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) == 0) {
return;
}
grpc_deadline_state* deadline_state = elem->call_data;
grpc_deadline_timer_state cur_state;
grpc_closure* closure = NULL;
retry:
cur_state =
(grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state);
switch (cur_state) {
case GRPC_DEADLINE_STATE_PENDING:
// Note: We do not start the timer if there is already a timer // Note: We do not start the timer if there is already a timer
// pending. This should be okay, because this is only called from two return;
// functions exported by this module: grpc_deadline_state_start(), which case GRPC_DEADLINE_STATE_FINISHED:
// starts the initial timer, and grpc_deadline_state_reset(), which if (gpr_atm_rel_cas(&deadline_state->timer_state,
// cancels any pre-existing timer before starting a new one. In GRPC_DEADLINE_STATE_FINISHED,
// particular, we want to ensure that if grpc_deadline_state_start() GRPC_DEADLINE_STATE_PENDING)) {
// winds up trying to start the timer after grpc_deadline_state_reset() // If we've already created and destroyed a timer, we always create a
// has already done so, we ignore the value from the former. // new closure: we have no other guarantee that the inlined closure is
if (!deadline_state->timer_pending && // not in use (it may hold a pending call to timer_callback)
gpr_time_cmp(deadline, gpr_inf_future(GPR_CLOCK_MONOTONIC)) != 0) { closure = grpc_closure_create(timer_callback, elem,
// Take a reference to the call stack, to be owned by the timer.
GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
deadline_state->timer_pending = true;
grpc_closure_init(&deadline_state->timer_callback, timer_callback, elem,
grpc_schedule_on_exec_ctx); grpc_schedule_on_exec_ctx);
grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, } else {
&deadline_state->timer_callback, goto retry;
gpr_now(GPR_CLOCK_MONOTONIC));
} }
break;
case GRPC_DEADLINE_STATE_INITIAL:
if (gpr_atm_rel_cas(&deadline_state->timer_state,
GRPC_DEADLINE_STATE_INITIAL,
GRPC_DEADLINE_STATE_PENDING)) {
closure =
grpc_closure_init(&deadline_state->timer_callback, timer_callback,
elem, grpc_schedule_on_exec_ctx);
} else {
goto retry;
} }
static void start_timer_if_needed(grpc_exec_ctx* exec_ctx, break;
grpc_call_element* elem, }
gpr_timespec deadline) { GPR_ASSERT(closure);
grpc_deadline_state* deadline_state = elem->call_data; GRPC_CALL_STACK_REF(deadline_state->call_stack, "deadline_timer");
gpr_mu_lock(&deadline_state->timer_mu); grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure,
start_timer_if_needed_locked(exec_ctx, elem, deadline); gpr_now(GPR_CLOCK_MONOTONIC));
gpr_mu_unlock(&deadline_state->timer_mu);
} }
// Cancels the deadline timer. // Cancels the deadline timer.
static void cancel_timer_if_needed_locked(grpc_exec_ctx* exec_ctx, static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_deadline_state* deadline_state) { grpc_deadline_state* deadline_state) {
if (deadline_state->timer_pending) { if (gpr_atm_rel_cas(&deadline_state->timer_state, GRPC_DEADLINE_STATE_PENDING,
GRPC_DEADLINE_STATE_FINISHED)) {
grpc_timer_cancel(exec_ctx, &deadline_state->timer); grpc_timer_cancel(exec_ctx, &deadline_state->timer);
deadline_state->timer_pending = false; } else {
// timer was either in STATE_INITAL (nothing to cancel)
// OR in STATE_FINISHED (again nothing to cancel)
} }
} }
static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
grpc_deadline_state* deadline_state) {
gpr_mu_lock(&deadline_state->timer_mu);
cancel_timer_if_needed_locked(exec_ctx, deadline_state);
gpr_mu_unlock(&deadline_state->timer_mu);
}
// Callback run when the call is complete. // Callback run when the call is complete.
static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { static void on_complete(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
grpc_deadline_state* deadline_state = arg; grpc_deadline_state* deadline_state = arg;
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(exec_ctx, deadline_state);
// Invoke the next callback. // Invoke the next callback.
deadline_state->next_on_complete->cb( grpc_closure_run(exec_ctx, deadline_state->next_on_complete,
exec_ctx, deadline_state->next_on_complete->cb_arg, error); GRPC_ERROR_REF(error));
} }
// Inject our own on_complete callback into op. // Inject our own on_complete callback into op.
@ -138,14 +146,12 @@ void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
grpc_deadline_state* deadline_state = elem->call_data; grpc_deadline_state* deadline_state = elem->call_data;
memset(deadline_state, 0, sizeof(*deadline_state)); memset(deadline_state, 0, sizeof(*deadline_state));
deadline_state->call_stack = call_stack; deadline_state->call_stack = call_stack;
gpr_mu_init(&deadline_state->timer_mu);
} }
void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx, void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem) { grpc_call_element* elem) {
grpc_deadline_state* deadline_state = elem->call_data; grpc_deadline_state* deadline_state = elem->call_data;
cancel_timer_if_needed(exec_ctx, deadline_state); cancel_timer_if_needed(exec_ctx, deadline_state);
gpr_mu_destroy(&deadline_state->timer_mu);
} }
// Callback and associated state for starting the timer after call stack // Callback and associated state for starting the timer after call stack
@ -187,10 +193,8 @@ void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem, void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
gpr_timespec new_deadline) { gpr_timespec new_deadline) {
grpc_deadline_state* deadline_state = elem->call_data; grpc_deadline_state* deadline_state = elem->call_data;
gpr_mu_lock(&deadline_state->timer_mu); cancel_timer_if_needed(exec_ctx, deadline_state);
cancel_timer_if_needed_locked(exec_ctx, deadline_state); start_timer_if_needed(exec_ctx, elem, new_deadline);
start_timer_if_needed_locked(exec_ctx, elem, new_deadline);
gpr_mu_unlock(&deadline_state->timer_mu);
} }
void grpc_deadline_state_client_start_transport_stream_op( void grpc_deadline_state_client_start_transport_stream_op(
@ -244,7 +248,7 @@ typedef struct server_call_data {
// Constructor for call_data. Used for both client and server filters. // Constructor for call_data. Used for both client and server filters.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem, grpc_call_element* elem,
grpc_call_element_args* args) { const grpc_call_element_args* args) {
// Note: size of call data is different between client and server. // Note: size of call data is different between client and server.
memset(elem->call_data, 0, elem->filter->sizeof_call_data); memset(elem->call_data, 0, elem->filter->sizeof_call_data);
grpc_deadline_state_init(exec_ctx, elem, args->call_stack); grpc_deadline_state_init(exec_ctx, elem, args->call_stack);

@ -35,16 +35,18 @@
#include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
typedef enum grpc_deadline_timer_state {
GRPC_DEADLINE_STATE_INITIAL,
GRPC_DEADLINE_STATE_PENDING,
GRPC_DEADLINE_STATE_FINISHED
} grpc_deadline_timer_state;
// State used for filters that enforce call deadlines. // State used for filters that enforce call deadlines.
// Must be the first field in the filter's call_data. // Must be the first field in the filter's call_data.
typedef struct grpc_deadline_state { typedef struct grpc_deadline_state {
// We take a reference to the call stack for the timer callback. // We take a reference to the call stack for the timer callback.
grpc_call_stack* call_stack; grpc_call_stack* call_stack;
// Guards access to timer_pending and timer. gpr_atm timer_state;
gpr_mu timer_mu;
// True if the timer callback is currently pending.
bool timer_pending;
// The deadline timer.
grpc_timer timer; grpc_timer timer;
grpc_closure timer_callback; grpc_closure timer_callback;
// Closure to invoke when the call is complete. // Closure to invoke when the call is complete.

@ -386,7 +386,7 @@ static void hc_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
calld->on_done_recv_initial_metadata = NULL; calld->on_done_recv_initial_metadata = NULL;
calld->on_done_recv_trailing_metadata = NULL; calld->on_done_recv_trailing_metadata = NULL;

@ -343,7 +343,7 @@ static void hs_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
/* initialize members */ /* initialize members */

@ -166,7 +166,7 @@ static void start_transport_stream_op(grpc_exec_ctx* exec_ctx,
// Constructor for call_data. // Constructor for call_data.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx, static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem, grpc_call_element* elem,
grpc_call_element_args* args) { const grpc_call_element_args* args) {
channel_data* chand = elem->channel_data; channel_data* chand = elem->channel_data;
call_data* calld = elem->call_data; call_data* calld = elem->call_data;
calld->next_recv_message_ready = NULL; calld->next_recv_message_ready = NULL;

@ -113,14 +113,15 @@ static grpc_error *try_split_host_port(const char *name,
/* parse name, splitting it into host and port parts */ /* parse name, splitting it into host and port parts */
grpc_error *error; grpc_error *error;
gpr_split_host_port(name, host, port); gpr_split_host_port(name, host, port);
if (host == NULL) { if (*host == NULL) {
char *msg; char *msg;
gpr_asprintf(&msg, "unparseable host:port: '%s'", name); gpr_asprintf(&msg, "unparseable host:port: '%s'", name);
error = GRPC_ERROR_CREATE(msg); error = GRPC_ERROR_CREATE(msg);
gpr_free(msg); gpr_free(msg);
return error; return error;
} }
if (port == NULL) { if (*port == NULL) {
// TODO(murgatroid99): add tests for this case
if (default_port == NULL) { if (default_port == NULL) {
char *msg; char *msg;
gpr_asprintf(&msg, "no port in name '%s'", name); gpr_asprintf(&msg, "no port in name '%s'", name);

@ -41,8 +41,12 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) { const char *grpc_inet_ntop(int af, const void *src, char *dst, size_t size) {
#ifdef GPR_WIN_INET_NTOP
return inet_ntop(af, src, dst, size);
#else
/* Windows InetNtopA wants a mutable ip pointer */ /* Windows InetNtopA wants a mutable ip pointer */
return InetNtopA(af, (void *)src, dst, size); return InetNtopA(af, (void *)src, dst, size);
#endif /* GPR_WIN_INET_NTOP */
} }
#endif /* GRPC_WINDOWS_SOCKETUTILS */ #endif /* GRPC_WINDOWS_SOCKETUTILS */

@ -46,6 +46,8 @@
#include "src/core/lib/iomgr/tcp_uv.h" #include "src/core/lib/iomgr/tcp_uv.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
extern int grpc_tcp_trace;
typedef struct grpc_uv_tcp_connect { typedef struct grpc_uv_tcp_connect {
uv_connect_t connect_req; uv_connect_t connect_req;
grpc_timer alarm; grpc_timer alarm;
@ -70,6 +72,12 @@ static void uv_tc_on_alarm(grpc_exec_ctx *exec_ctx, void *acp,
grpc_error *error) { grpc_error *error) {
int done; int done;
grpc_uv_tcp_connect *connect = acp; grpc_uv_tcp_connect *connect = acp;
if (grpc_tcp_trace) {
const char *str = grpc_error_string(error);
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s",
connect->addr_name, str);
grpc_error_free_string(str);
}
if (error == GRPC_ERROR_NONE) { if (error == GRPC_ERROR_NONE) {
/* error == NONE implies that the timer ran out, and wasn't cancelled. If /* error == NONE implies that the timer ran out, and wasn't cancelled. If
it was cancelled, then the handler that cancelled it also should close it was cancelled, then the handler that cancelled it also should close
@ -145,6 +153,12 @@ static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
connect->resource_quota = resource_quota; connect->resource_quota = resource_quota;
uv_tcp_init(uv_default_loop(), connect->tcp_handle); uv_tcp_init(uv_default_loop(), connect->tcp_handle);
connect->connect_req.data = connect; connect->connect_req.data = connect;
if (grpc_tcp_trace) {
gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
connect->addr_name);
}
// TODO(murgatroid99): figure out what the return value here means // TODO(murgatroid99): figure out what the return value here means
uv_tcp_connect(&connect->connect_req, connect->tcp_handle, uv_tcp_connect(&connect->connect_req, connect->tcp_handle,
(const struct sockaddr *)resolved_addr->addr, (const struct sockaddr *)resolved_addr->addr,

@ -180,25 +180,25 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
GPR_ASSERT(now.clock_type == g_clock_type); GPR_ASSERT(now.clock_type == g_clock_type);
timer->closure = closure; timer->closure = closure;
timer->deadline = deadline; timer->deadline = deadline;
timer->triggered = 0;
if (!g_initialized) { if (!g_initialized) {
timer->triggered = 1; timer->pending = false;
grpc_closure_sched( grpc_closure_sched(
exec_ctx, timer->closure, exec_ctx, timer->closure,
GRPC_ERROR_CREATE("Attempt to create timer before initialization")); GRPC_ERROR_CREATE("Attempt to create timer before initialization"));
return; return;
} }
gpr_mu_lock(&shard->mu);
timer->pending = true;
if (gpr_time_cmp(deadline, now) <= 0) { if (gpr_time_cmp(deadline, now) <= 0) {
timer->triggered = 1; timer->pending = false;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
gpr_mu_unlock(&shard->mu);
/* early out */
return; return;
} }
/* TODO(ctiller): check deadline expired */
gpr_mu_lock(&shard->mu);
grpc_time_averaged_stats_add_sample(&shard->stats, grpc_time_averaged_stats_add_sample(&shard->stats,
ts_to_dbl(gpr_time_sub(deadline, now))); ts_to_dbl(gpr_time_sub(deadline, now)));
if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) { if (gpr_time_cmp(deadline, shard->queue_deadline_cap) < 0) {
@ -243,9 +243,9 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)]; shard_type *shard = &g_shards[GPR_HASH_POINTER(timer, NUM_SHARDS)];
gpr_mu_lock(&shard->mu); gpr_mu_lock(&shard->mu);
if (!timer->triggered) { if (timer->pending) {
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED); grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
timer->triggered = 1; timer->pending = false;
if (timer->heap_index == INVALID_HEAP_INDEX) { if (timer->heap_index == INVALID_HEAP_INDEX) {
list_remove(timer); list_remove(timer);
} else { } else {
@ -296,7 +296,7 @@ static grpc_timer *pop_one(shard_type *shard, gpr_timespec now) {
} }
timer = grpc_timer_heap_top(&shard->heap); timer = grpc_timer_heap_top(&shard->heap);
if (gpr_time_cmp(timer->deadline, now) > 0) return NULL; if (gpr_time_cmp(timer->deadline, now) > 0) return NULL;
timer->triggered = 1; timer->pending = false;
grpc_timer_heap_pop(&shard->heap); grpc_timer_heap_pop(&shard->heap);
return timer; return timer;
} }

@ -40,7 +40,7 @@
struct grpc_timer { struct grpc_timer {
gpr_timespec deadline; gpr_timespec deadline;
uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */ uint32_t heap_index; /* INVALID_HEAP_INDEX if not in heap */
int triggered; bool pending;
struct grpc_timer *next; struct grpc_timer *next;
struct grpc_timer *prev; struct grpc_timer *prev;
grpc_closure *closure; grpc_closure *closure;

@ -53,8 +53,8 @@ static void stop_uv_timer(uv_timer_t *handle) {
void run_expired_timer(uv_timer_t *handle) { void run_expired_timer(uv_timer_t *handle) {
grpc_timer *timer = (grpc_timer *)handle->data; grpc_timer *timer = (grpc_timer *)handle->data;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GPR_ASSERT(!timer->triggered); GPR_ASSERT(timer->pending);
timer->triggered = 1; timer->pending = 0;
grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE); grpc_closure_sched(&exec_ctx, timer->closure, GRPC_ERROR_NONE);
stop_uv_timer(handle); stop_uv_timer(handle);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
@ -67,11 +67,11 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
uv_timer_t *uv_timer; uv_timer_t *uv_timer;
timer->closure = closure; timer->closure = closure;
if (gpr_time_cmp(deadline, now) <= 0) { if (gpr_time_cmp(deadline, now) <= 0) {
timer->triggered = 1; timer->pending = 0;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE); grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_NONE);
return; return;
} }
timer->triggered = 0; timer->pending = 1;
timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now)); timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
uv_timer = gpr_malloc(sizeof(uv_timer_t)); uv_timer = gpr_malloc(sizeof(uv_timer_t));
uv_timer_init(uv_default_loop(), uv_timer); uv_timer_init(uv_default_loop(), uv_timer);
@ -81,8 +81,8 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
} }
void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) { void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer) {
if (!timer->triggered) { if (timer->pending) {
timer->triggered = 1; timer->pending = 0;
grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED); grpc_closure_sched(exec_ctx, timer->closure, GRPC_ERROR_CANCELLED);
stop_uv_timer((uv_timer_t *)timer->uv_timer); stop_uv_timer((uv_timer_t *)timer->uv_timer);
} }

@ -41,7 +41,7 @@ struct grpc_timer {
/* This is actually a uv_timer_t*, but we want to keep platform-specific /* This is actually a uv_timer_t*, but we want to keep platform-specific
types out of headers */ types out of headers */
void *uv_timer; void *uv_timer;
int triggered; int pending;
}; };
#endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */ #endif /* GRPC_CORE_LIB_IOMGR_TIMER_UV_H */

@ -302,7 +302,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
memset(calld, 0, sizeof(*calld)); memset(calld, 0, sizeof(*calld));
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -197,7 +197,7 @@ static void auth_start_transport_op(grpc_exec_ctx *exec_ctx,
/* Constructor for call_data */ /* Constructor for call_data */
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
/* grab pointers to our data from the call element */ /* grab pointers to our data from the call element */
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;

@ -101,6 +101,17 @@ typedef struct {
grpc_error *error; grpc_error *error;
} received_status; } received_status;
static gpr_atm pack_received_status(received_status r) {
return r.is_set ? (1 | (gpr_atm)r.error) : 0;
}
static received_status unpack_received_status(gpr_atm atm) {
return (atm & 1) == 0
? (received_status){.is_set = false, .error = GRPC_ERROR_NONE}
: (received_status){.is_set = true,
.error = (grpc_error *)(atm & ~(gpr_atm)1)};
}
#define MAX_ERRORS_PER_BATCH 3 #define MAX_ERRORS_PER_BATCH 3
typedef struct batch_control { typedef struct batch_control {
@ -142,8 +153,6 @@ struct grpc_call {
bool destroy_called; bool destroy_called;
/** flag indicating that cancellation is inherited */ /** flag indicating that cancellation is inherited */
bool cancellation_is_inherited; bool cancellation_is_inherited;
/** bitmask of live batches */
uint8_t used_batches;
/** which ops are in-flight */ /** which ops are in-flight */
bool sent_initial_metadata; bool sent_initial_metadata;
bool sending_message; bool sending_message;
@ -165,8 +174,8 @@ struct grpc_call {
Element 0 is initial metadata, element 1 is trailing metadata. */ Element 0 is initial metadata, element 1 is trailing metadata. */
grpc_metadata_array *buffered_metadata[2]; grpc_metadata_array *buffered_metadata[2];
/* Received call statuses from various sources */ /* Packed received call statuses from various sources */
received_status status[STATUS_SOURCE_COUNT]; gpr_atm status[STATUS_SOURCE_COUNT];
/* Call data useful used for reporting. Only valid after the call has /* Call data useful used for reporting. Only valid after the call has
* completed */ * completed */
@ -446,7 +455,8 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
GRPC_ERROR_UNREF(c->status[i].error); GRPC_ERROR_UNREF(
unpack_received_status(gpr_atm_no_barrier_load(&c->status[i])).error);
} }
grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c); grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info, c);
@ -614,13 +624,12 @@ static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
*/ */
static bool get_final_status_from( static bool get_final_status_from(
grpc_call *call, status_source from_source, bool allow_ok_status, grpc_call *call, grpc_error *error, bool allow_ok_status,
void (*set_value)(grpc_status_code code, void *user_data), void (*set_value)(grpc_status_code code, void *user_data),
void *set_value_user_data, grpc_slice *details) { void *set_value_user_data, grpc_slice *details) {
grpc_status_code code; grpc_status_code code;
const char *msg = NULL; const char *msg = NULL;
grpc_error_get_status(call->status[from_source].error, call->send_deadline, grpc_error_get_status(error, call->send_deadline, &code, &msg, NULL);
&code, &msg, NULL);
if (code == GRPC_STATUS_OK && !allow_ok_status) { if (code == GRPC_STATUS_OK && !allow_ok_status) {
return false; return false;
} }
@ -638,12 +647,15 @@ static void get_final_status(grpc_call *call,
void *user_data), void *user_data),
void *set_value_user_data, grpc_slice *details) { void *set_value_user_data, grpc_slice *details) {
int i; int i;
received_status status[STATUS_SOURCE_COUNT];
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
}
if (grpc_call_error_trace) { if (grpc_call_error_trace) {
gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR"); gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) { if (status[i].is_set) {
gpr_log(GPR_DEBUG, " %d: %s", i, gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
grpc_error_string(call->status[i].error));
} }
} }
} }
@ -653,9 +665,9 @@ static void get_final_status(grpc_call *call,
/* search for the best status we can present: ideally the error we use has a /* search for the best status we can present: ideally the error we use has a
clearly defined grpc-status, and we'll prefer that. */ clearly defined grpc-status, and we'll prefer that. */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set && if (status[i].is_set &&
grpc_error_has_clear_grpc_status(call->status[i].error)) { grpc_error_has_clear_grpc_status(status[i].error)) {
if (get_final_status_from(call, (status_source)i, allow_ok_status != 0, if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
set_value, set_value_user_data, details)) { set_value, set_value_user_data, details)) {
return; return;
} }
@ -663,8 +675,8 @@ static void get_final_status(grpc_call *call,
} }
/* If no clearly defined status exists, search for 'anything' */ /* If no clearly defined status exists, search for 'anything' */
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) { if (status[i].is_set) {
if (get_final_status_from(call, (status_source)i, allow_ok_status != 0, if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
set_value, set_value_user_data, details)) { set_value, set_value_user_data, details)) {
return; return;
} }
@ -681,12 +693,13 @@ static void get_final_status(grpc_call *call,
static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call, static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
status_source source, grpc_error *error) { status_source source, grpc_error *error) {
if (call->status[source].is_set) { if (!gpr_atm_rel_cas(&call->status[source],
pack_received_status((received_status){
.is_set = false, .error = GRPC_ERROR_NONE}),
pack_received_status((received_status){
.is_set = true, .error = error}))) {
GRPC_ERROR_UNREF(error); GRPC_ERROR_UNREF(error);
return;
} }
call->status[source].is_set = true;
call->status[source].error = error;
} }
/******************************************************************************* /*******************************************************************************
@ -997,25 +1010,48 @@ static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
return !(flags & invalid_positions); return !(flags & invalid_positions);
} }
static batch_control *allocate_batch_control(grpc_call *call) { static int batch_slot_for_op(grpc_op_type type) {
size_t i; switch (type) {
for (i = 0; i < MAX_CONCURRENT_BATCHES; i++) { case GRPC_OP_SEND_INITIAL_METADATA:
if ((call->used_batches & (1 << i)) == 0) { return 0;
call->used_batches = (uint8_t)(call->used_batches | (uint8_t)(1 << i)); case GRPC_OP_SEND_MESSAGE:
return &call->active_batches[i]; return 1;
case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
case GRPC_OP_SEND_STATUS_FROM_SERVER:
return 2;
case GRPC_OP_RECV_INITIAL_METADATA:
return 3;
case GRPC_OP_RECV_MESSAGE:
return 4;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
case GRPC_OP_RECV_STATUS_ON_CLIENT:
return 5;
} }
GPR_UNREACHABLE_CODE(return 123456789);
} }
static batch_control *allocate_batch_control(grpc_call *call,
const grpc_op *ops,
size_t num_ops) {
int slot = batch_slot_for_op(ops[0].op);
for (size_t i = 1; i < num_ops; i++) {
int op_slot = batch_slot_for_op(ops[i].op);
slot = GPR_MIN(slot, op_slot);
}
batch_control *bctl = &call->active_batches[slot];
if (bctl->call != NULL) {
return NULL; return NULL;
} }
memset(bctl, 0, sizeof(*bctl));
bctl->call = call;
return bctl;
}
static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data, static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_cq_completion *storage) { grpc_cq_completion *storage) {
batch_control *bctl = user_data; batch_control *bctl = user_data;
grpc_call *call = bctl->call; grpc_call *call = bctl->call;
gpr_mu_lock(&call->mu); bctl->call = NULL;
call->used_batches = (uint8_t)(
call->used_batches & ~(uint8_t)(1 << (bctl - call->active_batches)));
gpr_mu_unlock(&call->mu);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion"); GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
} }
@ -1098,12 +1134,8 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
if (bctl->is_notify_tag_closure) { if (bctl->is_notify_tag_closure) {
/* unrefs bctl->error */ /* unrefs bctl->error */
bctl->call = NULL;
grpc_closure_run(exec_ctx, bctl->notify_tag, error); grpc_closure_run(exec_ctx, bctl->notify_tag, error);
gpr_mu_lock(&call->mu);
bctl->call->used_batches =
(uint8_t)(bctl->call->used_batches &
~(uint8_t)(1 << (bctl - bctl->call->active_batches)));
gpr_mu_unlock(&call->mu);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion"); GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
} else { } else {
/* unrefs bctl->error */ /* unrefs bctl->error */
@ -1315,6 +1347,11 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
finish_batch_step(exec_ctx, bctl); finish_batch_step(exec_ctx, bctl);
} }
static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p,
grpc_cq_completion *completion) {
gpr_free(completion);
}
static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_call *call, const grpc_op *ops, grpc_call *call, const grpc_op *ops,
size_t nops, void *notify_tag, size_t nops, void *notify_tag,
@ -1329,32 +1366,34 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
grpc_metadata compression_md; grpc_metadata compression_md;
GPR_TIMER_BEGIN("grpc_call_start_batch", 0); GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag); GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
/* TODO(ctiller): this feels like it could be made lock-free */
gpr_mu_lock(&call->mu);
bctl = allocate_batch_control(call);
memset(bctl, 0, sizeof(*bctl));
bctl->call = call;
bctl->notify_tag = notify_tag;
bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
grpc_transport_stream_op *stream_op = &bctl->op;
memset(stream_op, 0, sizeof(*stream_op));
stream_op->covered_by_poller = true;
if (nops == 0) { if (nops == 0) {
GRPC_CALL_INTERNAL_REF(call, "completion");
if (!is_notify_tag_closure) { if (!is_notify_tag_closure) {
grpc_cq_begin_op(call->cq, notify_tag); grpc_cq_begin_op(call->cq, notify_tag);
grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
free_no_op_completion, NULL,
gpr_malloc(sizeof(grpc_cq_completion)));
} else {
grpc_closure_sched(exec_ctx, notify_tag, GRPC_ERROR_NONE);
} }
gpr_mu_unlock(&call->mu);
post_batch_completion(exec_ctx, bctl);
error = GRPC_CALL_OK; error = GRPC_CALL_OK;
goto done; goto done;
} }
/* TODO(ctiller): this feels like it could be made lock-free */
bctl = allocate_batch_control(call, ops, nops);
if (bctl == NULL) {
return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
}
bctl->notify_tag = notify_tag;
bctl->is_notify_tag_closure = (uint8_t)(is_notify_tag_closure != 0);
gpr_mu_lock(&call->mu);
grpc_transport_stream_op *stream_op = &bctl->op;
memset(stream_op, 0, sizeof(*stream_op));
stream_op->covered_by_poller = true;
/* rewrite batch ops into a transport op */ /* rewrite batch ops into a transport op */
for (i = 0; i < nops; i++) { for (i = 0; i < nops; i++) {
op = &ops[i]; op = &ops[i];

@ -122,7 +122,7 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx,
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
gpr_atm_no_barrier_store(&calld->filled_metadata, 0); gpr_atm_no_barrier_store(&calld->filled_metadata, 0);
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -879,7 +879,7 @@ static void channel_connectivity_changed(grpc_exec_ctx *exec_ctx, void *cd,
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
call_data *calld = elem->call_data; call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data; channel_data *chand = elem->channel_data;
memset(calld, 0, sizeof(call_data)); memset(calld, 0, sizeof(call_data));
@ -1198,7 +1198,9 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
crm->server_registered_method = rm; crm->server_registered_method = rm;
crm->flags = rm->flags; crm->flags = rm->flags;
crm->has_host = has_host; crm->has_host = has_host;
if (has_host) {
crm->host = host; crm->host = host;
}
crm->method = method; crm->method = method;
} }
GPR_ASSERT(slots <= UINT32_MAX); GPR_ASSERT(slots <= UINT32_MAX);

@ -244,7 +244,7 @@ class CallData {
/// Initializes the call data. /// Initializes the call data.
virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data, virtual grpc_error *Init(grpc_exec_ctx *exec_ctx, ChannelData *channel_data,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }
@ -308,7 +308,7 @@ class ChannelFilter final {
static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx, static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data; ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
// Construct the object in the already-allocated memory. // Construct the object in the already-allocated memory.
CallDataType *call_data = new (elem->call_data) CallDataType(); CallDataType *call_data = new (elem->call_data) CallDataType();

@ -189,8 +189,7 @@ class Server::SyncRequest final : public CompletionQueueTag {
explicit CallData(Server* server, SyncRequest* mrd) explicit CallData(Server* server, SyncRequest* mrd)
: cq_(mrd->cq_), : cq_(mrd->cq_),
call_(mrd->call_, server, &cq_, server->max_receive_message_size()), call_(mrd->call_, server, &cq_, server->max_receive_message_size()),
ctx_(mrd->deadline_, mrd->request_metadata_.metadata, ctx_(mrd->deadline_, &mrd->request_metadata_),
mrd->request_metadata_.count),
has_request_payload_(mrd->has_request_payload_), has_request_payload_(mrd->has_request_payload_),
request_payload_(mrd->request_payload_), request_payload_(mrd->request_payload_),
method_(mrd->method_) { method_(mrd->method_) {

@ -33,7 +33,9 @@
#include <grpc++/server_context.h> #include <grpc++/server_context.h>
#include <algorithm>
#include <mutex> #include <mutex>
#include <utility>
#include <grpc++/completion_queue.h> #include <grpc++/completion_queue.h>
#include <grpc++/impl/call.h> #include <grpc++/impl/call.h>
@ -133,8 +135,7 @@ ServerContext::ServerContext()
sent_initial_metadata_(false), sent_initial_metadata_(false),
compression_level_set_(false) {} compression_level_set_(false) {}
ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata, ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr)
size_t metadata_count)
: completion_op_(nullptr), : completion_op_(nullptr),
has_notify_when_done_tag_(false), has_notify_when_done_tag_(false),
async_notify_when_done_tag_(nullptr), async_notify_when_done_tag_(nullptr),
@ -143,12 +144,8 @@ ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
cq_(nullptr), cq_(nullptr),
sent_initial_metadata_(false), sent_initial_metadata_(false),
compression_level_set_(false) { compression_level_set_(false) {
for (size_t i = 0; i < metadata_count; i++) { std::swap(*client_metadata_.arr(), *arr);
client_metadata_.map()->insert( client_metadata_.FillMap();
std::pair<grpc::string_ref, grpc::string_ref>(
StringRefFromSlice(&metadata[i].key),
StringRefFromSlice(&metadata[i].value)));
}
} }
ServerContext::~ServerContext() { ServerContext::~ServerContext() {

@ -7,19 +7,19 @@ A C# implementation of gRPC.
SUPPORTED PLATFORMS SUPPORTED PLATFORMS
------------------ ------------------
- [.NET Core](https://dotnet.github.io/) on Linux, Windows and Mac OS X
- .NET Framework 4.5+ (Windows) - .NET Framework 4.5+ (Windows)
- [.NET Core](https://dotnet.github.io/) on Linux, Windows and Mac OS X (starting from version 1.0.1)
- Mono 4+ on Linux, Windows and Mac OS X - Mono 4+ on Linux, Windows and Mac OS X
PREREQUISITES PREREQUISITES
-------------- --------------
When using gRPC C# under .NET Core you only need to [install .NET Core](https://www.microsoft.com/net/core).
- Windows: .NET Framework 4.5+, Visual Studio 2013 or 2015 - Windows: .NET Framework 4.5+, Visual Studio 2013 or 2015
- Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed) - Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed)
- Mac OS X: Xamarin Studio 5.9+ - Mac OS X: Xamarin Studio 5.9+
HOW TO USE HOW TO USE
-------------- --------------
@ -71,23 +71,10 @@ DOCUMENTATION
- [Helloworld Example][] - [Helloworld Example][]
- [RouteGuide Tutorial][] - [RouteGuide Tutorial][]
CONTENTS PERFORMANCE
-------- -----------
- ext: For best gRPC C# performance, use [.NET Core](https://dotnet.github.io/) and the Server GC mode `"System.GC.Server": true` for your applications.
The extension library that wraps C API to be more digestible by C#.
- Grpc.Auth:
gRPC OAuth2/JWT support.
- Grpc.Core:
The main gRPC C# library.
- Grpc.Examples:
API examples for math.proto
- Grpc.Examples.MathClient:
An example client that sends requests to math server.
- Grpc.Examples.MathServer:
An example server that implements a simple math service.
- Grpc.IntegrationTesting:
Cross-language gRPC implementation testing (interop testing).
THE NATIVE DEPENDENCY THE NATIVE DEPENDENCY
--------------- ---------------

@ -78,6 +78,8 @@ class CompletionQueueAsyncWorker : public Nan::AsyncWorker {
void HandleErrorCallback(); void HandleErrorCallback();
private: private:
static void TryAddWorker();
grpc_event result; grpc_event result;
static grpc_completion_queue *queue; static grpc_completion_queue *queue;
@ -118,20 +120,21 @@ void CompletionQueueAsyncWorker::Execute() {
grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; } grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; }
void CompletionQueueAsyncWorker::Next() { void CompletionQueueAsyncWorker::TryAddWorker() {
#ifndef GRPC_UV if (current_threads < max_queue_threads && waiting_next_calls > 0) {
Nan::HandleScope scope;
if (current_threads < max_queue_threads) {
current_threads += 1; current_threads += 1;
waiting_next_calls -= 1;
CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker(); CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
Nan::AsyncQueueWorker(worker); Nan::AsyncQueueWorker(worker);
} else {
waiting_next_calls += 1;
} }
GPR_ASSERT(current_threads <= max_queue_threads); GPR_ASSERT(current_threads <= max_queue_threads);
GPR_ASSERT((current_threads == max_queue_threads) || GPR_ASSERT((current_threads == max_queue_threads) ||
(waiting_next_calls == 0)); (waiting_next_calls == 0));
#endif }
void CompletionQueueAsyncWorker::Next() {
waiting_next_calls += 1;
TryAddWorker();
} }
void CompletionQueueAsyncWorker::Init(Local<Object> exports) { void CompletionQueueAsyncWorker::Init(Local<Object> exports) {
@ -143,17 +146,8 @@ void CompletionQueueAsyncWorker::Init(Local<Object> exports) {
void CompletionQueueAsyncWorker::HandleOKCallback() { void CompletionQueueAsyncWorker::HandleOKCallback() {
Nan::HandleScope scope; Nan::HandleScope scope;
if (waiting_next_calls > 0) {
waiting_next_calls -= 1;
// Old worker removed, new worker added. current_threads += 0
CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
Nan::AsyncQueueWorker(worker);
} else {
current_threads -= 1; current_threads -= 1;
} TryAddWorker();
GPR_ASSERT(current_threads <= max_queue_threads);
GPR_ASSERT((current_threads == max_queue_threads) ||
(waiting_next_calls == 0));
Nan::Callback *callback = GetTagCallback(result.tag); Nan::Callback *callback = GetTagCallback(result.tag);
Local<Value> argv[] = {Nan::Null(), GetTagNodeValue(result.tag)}; Local<Value> argv[] = {Nan::Null(), GetTagNodeValue(result.tag)};
callback->Call(2, argv); callback->Call(2, argv);
@ -162,18 +156,9 @@ void CompletionQueueAsyncWorker::HandleOKCallback() {
} }
void CompletionQueueAsyncWorker::HandleErrorCallback() { void CompletionQueueAsyncWorker::HandleErrorCallback() {
if (waiting_next_calls > 0) {
waiting_next_calls -= 1;
// Old worker removed, new worker added. current_threads += 0
CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker();
Nan::AsyncQueueWorker(worker);
} else {
current_threads -= 1;
}
GPR_ASSERT(current_threads <= max_queue_threads);
GPR_ASSERT((current_threads == max_queue_threads) ||
(waiting_next_calls == 0));
Nan::HandleScope scope; Nan::HandleScope scope;
current_threads -= 1;
TryAddWorker();
Nan::Callback *callback = GetTagCallback(result.tag); Nan::Callback *callback = GetTagCallback(result.tag);
Local<Value> argv[] = {Nan::Error(ErrorMessage())}; Local<Value> argv[] = {Nan::Error(ErrorMessage())};
@ -189,6 +174,7 @@ grpc_completion_queue *GetCompletionQueue() {
} }
void CompletionQueueNext() { void CompletionQueueNext() {
gpr_log(GPR_DEBUG, "Called CompletionQueueNext");
CompletionQueueAsyncWorker::Next(); CompletionQueueAsyncWorker::Next();
} }

@ -108,7 +108,7 @@ function _write(chunk, encoding, callback) {
but passing an object that causes a serialization failure is a misuse but passing an object that causes a serialization failure is a misuse
of the API anyway, so that's OK. The primary purpose here is to give the of the API anyway, so that's OK. The primary purpose here is to give the
programmer a useful error and to stop the stream properly */ programmer a useful error and to stop the stream properly */
this.call.cancelWithStatus(grpc.status.INTERNAL, "Serialization failure"); this.call.cancelWithStatus(grpc.status.INTERNAL, 'Serialization failure');
callback(e); callback(e);
} }
if (_.isFinite(encoding)) { if (_.isFinite(encoding)) {
@ -831,13 +831,12 @@ exports.waitForClientReady = function(client, deadline, callback) {
*/ */
exports.makeProtobufClientConstructor = function(service, options) { exports.makeProtobufClientConstructor = function(service, options) {
var method_attrs = common.getProtobufServiceAttrs(service, options); var method_attrs = common.getProtobufServiceAttrs(service, options);
var deprecatedArgumentOrder = false; if (!options) {
if (options) { options = {deprecatedArgumentOrder: false};
deprecatedArgumentOrder = options.deprecatedArgumentOrder;
} }
var Client = exports.makeClientConstructor( var Client = exports.makeClientConstructor(
method_attrs, common.fullyQualifiedName(service), method_attrs, common.fullyQualifiedName(service),
deprecatedArgumentOrder); options);
Client.service = service; Client.service = service;
Client.service.grpc_options = options; Client.service.grpc_options = options;
return Client; return Client;

@ -121,20 +121,20 @@ function sendUnaryResponse(call, value, serialize, metadata, flags) {
if (metadata) { if (metadata) {
statusMetadata = metadata; statusMetadata = metadata;
} }
status.metadata = statusMetadata._getCoreRepresentation();
if (!call.metadataSent) {
end_batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
call.metadataSent = true;
}
var message; var message;
try { try {
message = serialize(value); message = serialize(value);
} catch (e) { } catch (e) {
e.code = grpc.status.INTERNAL; e.code = grpc.status.INTERNAL;
handleError(e); handleError(call, e);
return; return;
} }
status.metadata = statusMetadata._getCoreRepresentation();
if (!call.metadataSent) {
end_batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
call.metadataSent = true;
}
message.grpcWriteFlags = flags; message.grpcWriteFlags = flags;
end_batch[grpc.opType.SEND_MESSAGE] = message; end_batch[grpc.opType.SEND_MESSAGE] = message;
end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status; end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status;
@ -280,11 +280,6 @@ function _write(chunk, encoding, callback) {
/* jshint validthis: true */ /* jshint validthis: true */
var batch = {}; var batch = {};
var self = this; var self = this;
if (!this.call.metadataSent) {
batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
this.call.metadataSent = true;
}
var message; var message;
try { try {
message = this.serialize(chunk); message = this.serialize(chunk);
@ -293,6 +288,11 @@ function _write(chunk, encoding, callback) {
callback(e); callback(e);
return; return;
} }
if (!this.call.metadataSent) {
batch[grpc.opType.SEND_INITIAL_METADATA] =
(new Metadata())._getCoreRepresentation();
this.call.metadataSent = true;
}
if (_.isFinite(encoding)) { if (_.isFinite(encoding)) {
/* Attach the encoding if it is a finite number. This is the closest we /* Attach the encoding if it is a finite number. This is the closest we
* can get to checking that it is valid flags */ * can get to checking that it is valid flags */
@ -728,11 +728,17 @@ var defaultHandler = {
* method implementation for the provided service. * method implementation for the provided service.
*/ */
Server.prototype.addService = function(service, implementation) { Server.prototype.addService = function(service, implementation) {
if (!_.isObjectLike(service) || !_.isObjectLike(implementation)) {
throw new Error('addService requires two objects as arguments');
}
if (_.keys(service).length === 0) {
throw new Error('Cannot add an empty service to a server');
}
if (this.started) { if (this.started) {
throw new Error('Can\'t add a service to a started server.'); throw new Error('Can\'t add a service to a started server.');
} }
var self = this; var self = this;
_.each(service, function(attrs, name) { _.forOwn(service, function(attrs, name) {
var method_type; var method_type;
if (attrs.requestStream) { if (attrs.requestStream) {
if (attrs.responseStream) { if (attrs.responseStream) {

@ -607,6 +607,113 @@ describe('Client malformed response handling', function() {
call.end(); call.end();
}); });
}); });
describe('Server serialization failure handling', function() {
function serializeFail(obj) {
throw new Error('Serialization failed');
}
var client;
var server;
before(function() {
var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto');
var test_service = test_proto.lookup('TestService');
var malformed_test_service = {
unary: {
path: '/TestService/Unary',
requestStream: false,
responseStream: false,
requestDeserialize: _.identity,
responseSerialize: serializeFail
},
clientStream: {
path: '/TestService/ClientStream',
requestStream: true,
responseStream: false,
requestDeserialize: _.identity,
responseSerialize: serializeFail
},
serverStream: {
path: '/TestService/ServerStream',
requestStream: false,
responseStream: true,
requestDeserialize: _.identity,
responseSerialize: serializeFail
},
bidiStream: {
path: '/TestService/BidiStream',
requestStream: true,
responseStream: true,
requestDeserialize: _.identity,
responseSerialize: serializeFail
}
};
server = new grpc.Server();
server.addService(malformed_test_service, {
unary: function(call, cb) {
cb(null, {});
},
clientStream: function(stream, cb) {
stream.on('data', function() {/* Ignore requests */});
stream.on('end', function() {
cb(null, {});
});
},
serverStream: function(stream) {
stream.write({});
stream.end();
},
bidiStream: function(stream) {
stream.on('data', function() {
// Ignore requests
stream.write({});
});
stream.on('end', function() {
stream.end();
});
}
});
var port = server.bind('localhost:0', server_insecure_creds);
var Client = surface_client.makeProtobufClientConstructor(test_service);
client = new Client('localhost:' + port, grpc.credentials.createInsecure());
server.start();
});
after(function() {
server.forceShutdown();
});
it('should get an INTERNAL status with a unary call', function(done) {
client.unary({}, function(err, data) {
assert(err);
assert.strictEqual(err.code, grpc.status.INTERNAL);
done();
});
});
it('should get an INTERNAL status with a client stream call', function(done) {
var call = client.clientStream(function(err, data) {
assert(err);
assert.strictEqual(err.code, grpc.status.INTERNAL);
done();
});
call.write({});
call.end();
});
it('should get an INTERNAL status with a server stream call', function(done) {
var call = client.serverStream({});
call.on('data', function(){});
call.on('error', function(err) {
assert.strictEqual(err.code, grpc.status.INTERNAL);
done();
});
});
it('should get an INTERNAL status with a bidi stream call', function(done) {
var call = client.bidiStream();
call.on('data', function(){});
call.on('error', function(err) {
assert.strictEqual(err.code, grpc.status.INTERNAL);
done();
});
call.write({});
call.end();
});
});
describe('Other conditions', function() { describe('Other conditions', function() {
var test_service; var test_service;
var Client; var Client;

@ -321,44 +321,8 @@ unsigned int parse_h2_length(const char *field) {
grpc_metadata_array_init(&request_metadata_recv); grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details); grpc_call_details_init(&call_details);
memset(ops, 0, sizeof(ops)); __weak XCTestExpectation *expectation =
op = ops; [self expectationWithDescription:@"Coalescing"];
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_c;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = request_payload;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"Coalescing"];
dispatch_async( dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -425,6 +389,46 @@ unsigned int parse_h2_length(const char *field) {
[expectation fulfill]; [expectation fulfill];
}); });
// Guarantees that server is listening to the port before client connects.
sleep(1);
memset(ops, 0, sizeof(ops));
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 2;
op->data.send_initial_metadata.metadata = meta_c;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_MESSAGE;
op->data.send_message.send_message = request_payload;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_INITIAL_METADATA;
op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message.recv_message = &response_payload_recv;
op->flags = 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
op->data.recv_status_on_client.status = &status;
op->data.recv_status_on_client.status_details = &details;
op->flags = 0;
op->reserved = NULL;
op++;
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
CQ_EXPECT_COMPLETION(cqv, (void *)1, 1); CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
cq_verify(cqv); cq_verify(cqv);

@ -39,11 +39,10 @@ from grpc import _grpcio_metadata
from grpc._cython import cygrpc from grpc._cython import cygrpc
from grpc.framework.foundation import callable_util from grpc.framework.foundation import callable_util
_USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__) _USER_AGENT = 'grpc-python/{}'.format(_grpcio_metadata.__version__)
_EMPTY_FLAGS = 0 _EMPTY_FLAGS = 0
_INFINITE_FUTURE = cygrpc.Timespec(float('+inf')) _INFINITE_FUTURE = cygrpc.Timespec(float('+inf'))
_EMPTY_METADATA = cygrpc.Metadata(())
_UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata, _UNARY_UNARY_INITIAL_DUE = (cygrpc.OperationType.send_initial_metadata,
cygrpc.OperationType.send_message, cygrpc.OperationType.send_message,
@ -138,8 +137,8 @@ def _abort(state, code, details):
state.code = code state.code = code
state.details = details state.details = details
if state.initial_metadata is None: if state.initial_metadata is None:
state.initial_metadata = _EMPTY_METADATA state.initial_metadata = _common.EMPTY_METADATA
state.trailing_metadata = _EMPTY_METADATA state.trailing_metadata = _common.EMPTY_METADATA
def _handle_event(event, state, response_deserializer): def _handle_event(event, state, response_deserializer):
@ -435,7 +434,7 @@ def _start_unary_request(request, timeout, request_serializer):
deadline, deadline_timespec = _deadline(timeout) deadline, deadline_timespec = _deadline(timeout)
serialized_request = _common.serialize(request, request_serializer) serialized_request = _common.serialize(request, request_serializer)
if serialized_request is None: if serialized_request is None:
state = _RPCState((), _EMPTY_METADATA, _EMPTY_METADATA, state = _RPCState((), _common.EMPTY_METADATA, _common.EMPTY_METADATA,
grpc.StatusCode.INTERNAL, grpc.StatusCode.INTERNAL,
'Exception serializing request!') 'Exception serializing request!')
rendezvous = _Rendezvous(state, None, None, deadline) rendezvous = _Rendezvous(state, None, None, deadline)

@ -37,7 +37,7 @@ import six
import grpc import grpc
from grpc._cython import cygrpc from grpc._cython import cygrpc
_EMPTY_METADATA = cygrpc.Metadata(()) EMPTY_METADATA = cygrpc.Metadata(())
CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = { CYGRPC_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = {
cygrpc.ConnectivityState.idle: cygrpc.ConnectivityState.idle:
@ -107,7 +107,7 @@ def channel_args(options):
def cygrpc_metadata(application_metadata): def cygrpc_metadata(application_metadata):
return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata( return EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
cygrpc.Metadatum(encode(key), encode(value)) cygrpc.Metadatum(encode(key), encode(value))
for key, value in application_metadata) for key, value in application_metadata)

@ -57,7 +57,6 @@ _CLOSED = 'closed'
_CANCELLED = 'cancelled' _CANCELLED = 'cancelled'
_EMPTY_FLAGS = 0 _EMPTY_FLAGS = 0
_EMPTY_METADATA = cygrpc.Metadata(())
_UNEXPECTED_EXIT_SERVER_GRACE = 1.0 _UNEXPECTED_EXIT_SERVER_GRACE = 1.0
@ -143,7 +142,7 @@ def _abort(state, call, code, details):
effective_details = details if state.details is None else state.details effective_details = details if state.details is None else state.details
if state.initial_metadata_allowed: if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata( operations = (cygrpc.operation_send_initial_metadata(
_EMPTY_METADATA, _EMPTY_FLAGS), _common.EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_status_from_server( cygrpc.operation_send_status_from_server(
_common.cygrpc_metadata(state.trailing_metadata), _common.cygrpc_metadata(state.trailing_metadata),
effective_code, effective_details, _EMPTY_FLAGS),) effective_code, effective_details, _EMPTY_FLAGS),)
@ -416,7 +415,7 @@ def _send_response(rpc_event, state, serialized_response):
else: else:
if state.initial_metadata_allowed: if state.initial_metadata_allowed:
operations = (cygrpc.operation_send_initial_metadata( operations = (cygrpc.operation_send_initial_metadata(
_EMPTY_METADATA, _EMPTY_FLAGS), _common.EMPTY_METADATA, _EMPTY_FLAGS),
cygrpc.operation_send_message(serialized_response, cygrpc.operation_send_message(serialized_response,
_EMPTY_FLAGS),) _EMPTY_FLAGS),)
state.initial_metadata_allowed = False state.initial_metadata_allowed = False
@ -446,8 +445,8 @@ def _status(rpc_event, state, serialized_response):
] ]
if state.initial_metadata_allowed: if state.initial_metadata_allowed:
operations.append( operations.append(
cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, cygrpc.operation_send_initial_metadata(
_EMPTY_FLAGS)) _common.EMPTY_METADATA, _EMPTY_FLAGS))
if serialized_response is not None: if serialized_response is not None:
operations.append( operations.append(
cygrpc.operation_send_message(serialized_response, cygrpc.operation_send_message(serialized_response,
@ -549,11 +548,11 @@ def _find_method_handler(rpc_event, generic_handlers):
def _handle_unrecognized_method(rpc_event): def _handle_unrecognized_method(rpc_event):
operations = ( operations = (cygrpc.operation_send_initial_metadata(_common.EMPTY_METADATA,
cygrpc.operation_send_initial_metadata(_EMPTY_METADATA, _EMPTY_FLAGS), _EMPTY_FLAGS),
cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS), cygrpc.operation_receive_close_on_server(_EMPTY_FLAGS),
cygrpc.operation_send_status_from_server( cygrpc.operation_send_status_from_server(
_EMPTY_METADATA, cygrpc.StatusCode.unimplemented, _common.EMPTY_METADATA, cygrpc.StatusCode.unimplemented,
b'Method not found!', _EMPTY_FLAGS),) b'Method not found!', _EMPTY_FLAGS),)
rpc_state = _RPCState() rpc_state = _RPCState()
rpc_event.operation_call.start_server_batch( rpc_event.operation_call.start_server_batch(

@ -32,7 +32,7 @@ import unittest
import weakref import weakref
import grpc import grpc
from grpc import _grpcio_metadata from grpc import _channel
from grpc.framework.foundation import logging_pool from grpc.framework.foundation import logging_pool
from tests.unit import test_common from tests.unit import test_common
@ -49,8 +49,6 @@ _UNARY_STREAM = '/test/UnaryStream'
_STREAM_UNARY = '/test/StreamUnary' _STREAM_UNARY = '/test/StreamUnary'
_STREAM_STREAM = '/test/StreamStream' _STREAM_STREAM = '/test/StreamStream'
_USER_AGENT = 'Python-gRPC-{}'.format(_grpcio_metadata.__version__)
_CLIENT_METADATA = (('client-md-key', 'client-md-key'), _CLIENT_METADATA = (('client-md-key', 'client-md-key'),
('client-md-key-bin', b'\x00\x01')) ('client-md-key-bin', b'\x00\x01'))
@ -76,7 +74,7 @@ def validate_client_metadata(test, servicer_context):
_CLIENT_METADATA, servicer_context.invocation_metadata())) _CLIENT_METADATA, servicer_context.invocation_metadata()))
test.assertTrue( test.assertTrue(
user_agent(servicer_context.invocation_metadata()) user_agent(servicer_context.invocation_metadata())
.startswith('primary-agent ' + _USER_AGENT)) .startswith('primary-agent ' + _channel._USER_AGENT))
test.assertTrue( test.assertTrue(
user_agent(servicer_context.invocation_metadata()) user_agent(servicer_context.invocation_metadata())
.endswith('secondary-agent')) .endswith('secondary-agent'))

@ -102,7 +102,6 @@ $CFLAGS << ' -std=c99 '
$CFLAGS << ' -Wall ' $CFLAGS << ' -Wall '
$CFLAGS << ' -Wextra ' $CFLAGS << ' -Wextra '
$CFLAGS << ' -pedantic ' $CFLAGS << ' -pedantic '
$CFLAGS << ' -Werror '
$CFLAGS << ' -Wno-format ' $CFLAGS << ' -Wno-format '
output = File.join('grpc', 'grpc_c') output = File.join('grpc', 'grpc_c')

@ -1492,7 +1492,7 @@
out_mingbase = '$(LIBDIR)/$(CONFIG)/' + lib.name + '$(SHARED_VERSION_' + lang_to_var[lib.language] + ')' out_mingbase = '$(LIBDIR)/$(CONFIG)/' + lib.name + '$(SHARED_VERSION_' + lang_to_var[lib.language] + ')'
out_libbase = '$(LIBDIR)/$(CONFIG)/lib' + lib.name + '$(SHARED_VERSION_' + lang_to_var[lib.language] + ')' out_libbase = '$(LIBDIR)/$(CONFIG)/lib' + lib.name + '$(SHARED_VERSION_' + lang_to_var[lib.language] + ')'
common = '$(LIB' + lib.name.upper() + '_OBJS) $(LDLIBS)' common = '$(LIB' + lib.name.upper() + '_OBJS)'
link_libs = '' link_libs = ''
lib_deps = ' $(ZLIB_DEP)' lib_deps = ' $(ZLIB_DEP)'
@ -1542,6 +1542,8 @@
ldflags = '$(LDFLAGS)' ldflags = '$(LDFLAGS)'
if lib.get('LDFLAGS', None): if lib.get('LDFLAGS', None):
ldflags += ' ' + lib['LDFLAGS'] ldflags += ' ' + lib['LDFLAGS']
common = common + ' $(LDLIBS)'
%> %>
% if lib.build == "all": % if lib.build == "all":

@ -53,7 +53,9 @@
'conditions': [ 'conditions': [
['runtime=="node"', { ['runtime=="node"', {
'defines': [ 'defines': [
'GRPC_UV' # Disabling this while bugs are ironed out. Uncomment this to
# re-enable libuv integration in C core.
# 'GRPC_UV'
] ]
}], }],
['OS!="win" and runtime=="electron"', { ['OS!="win" and runtime=="electron"', {

@ -29,7 +29,7 @@
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb ) s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
s.add_dependency 'google-protobuf', '~> 3.1.0' s.add_dependency 'google-protobuf', '~> 3.1'
s.add_dependency 'googleauth', '~> 0.5.1' s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'bundler', '~> 1.9'
@ -37,7 +37,7 @@
s.add_development_dependency 'logging', '~> 2.0' s.add_development_dependency 'logging', '~> 2.0'
s.add_development_dependency 'simplecov', '~> 0.9' s.add_development_dependency 'simplecov', '~> 0.9'
s.add_development_dependency 'rake', '~> 10.4' s.add_development_dependency 'rake', '~> 10.4'
s.add_development_dependency 'rake-compiler', '~> 0.9' s.add_development_dependency 'rake-compiler', '~> 1.0'
s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1' s.add_development_dependency 'rake-compiler-dock', '~> 0.5.1'
s.add_development_dependency 'rspec', '~> 3.2' s.add_development_dependency 'rspec', '~> 3.2'
s.add_development_dependency 'rubocop', '~> 0.30.0' s.add_development_dependency 'rubocop', '~> 0.30.0'

@ -57,7 +57,7 @@ static grpc_error *channel_init_func(grpc_exec_ctx *exec_ctx,
static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx, static grpc_error *call_init_func(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
++*(int *)(elem->channel_data); ++*(int *)(elem->channel_data);
*(int *)(elem->call_data) = 0; *(int *)(elem->call_data) = 0;
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;

@ -36,14 +36,17 @@
#include <grpc/grpc.h> #include <grpc/grpc.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/resolver.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
static gpr_mu g_mu; static gpr_mu g_mu;
static bool g_fail_resolution = true; static bool g_fail_resolution = true;
static grpc_combiner *g_combiner;
static grpc_error *my_resolve_address(const char *name, const char *addr, static grpc_error *my_resolve_address(const char *name, const char *addr,
grpc_resolved_addresses **addrs) { grpc_resolved_addresses **addrs) {
@ -71,6 +74,7 @@ static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx,
grpc_resolver_args args; grpc_resolver_args args;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.uri = uri; args.uri = uri;
args.combiner = g_combiner;
grpc_resolver *resolver = grpc_resolver *resolver =
grpc_resolver_factory_create_resolver(exec_ctx, factory, &args); grpc_resolver_factory_create_resolver(exec_ctx, factory, &args);
grpc_resolver_factory_unref(factory); grpc_resolver_factory_unref(factory);
@ -96,11 +100,41 @@ static bool wait_loop(int deadline_seconds, gpr_event *ev) {
return false; return false;
} }
typedef struct next_args {
grpc_resolver *resolver;
grpc_channel_args **result;
grpc_closure *on_complete;
} next_args;
static void call_resolver_next_now_lock_taken(grpc_exec_ctx *exec_ctx,
void *arg,
grpc_error *error_unused) {
next_args *a = arg;
grpc_resolver_next_locked(exec_ctx, a->resolver, a->result, a->on_complete);
gpr_free(a);
}
static void call_resolver_next_after_locking(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver,
grpc_channel_args **result,
grpc_closure *on_complete) {
next_args *a = gpr_malloc(sizeof(*a));
a->resolver = resolver;
a->result = result;
a->on_complete = on_complete;
grpc_closure_sched(
exec_ctx,
grpc_closure_create(call_resolver_next_now_lock_taken, a,
grpc_combiner_scheduler(resolver->combiner, false)),
GRPC_ERROR_NONE);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
grpc_init(); grpc_init();
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
g_combiner = grpc_combiner_create(NULL);
grpc_blocking_resolve_address = my_resolve_address; grpc_blocking_resolve_address = my_resolve_address;
grpc_channel_args *result = (grpc_channel_args *)1; grpc_channel_args *result = (grpc_channel_args *)1;
@ -108,7 +142,7 @@ int main(int argc, char **argv) {
grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test"); grpc_resolver *resolver = create_resolver(&exec_ctx, "dns:test");
gpr_event ev1; gpr_event ev1;
gpr_event_init(&ev1); gpr_event_init(&ev1);
grpc_resolver_next( call_resolver_next_after_locking(
&exec_ctx, resolver, &result, &exec_ctx, resolver, &result,
grpc_closure_create(on_done, &ev1, grpc_schedule_on_exec_ctx)); grpc_closure_create(on_done, &ev1, grpc_schedule_on_exec_ctx));
grpc_exec_ctx_flush(&exec_ctx); grpc_exec_ctx_flush(&exec_ctx);
@ -117,7 +151,7 @@ int main(int argc, char **argv) {
gpr_event ev2; gpr_event ev2;
gpr_event_init(&ev2); gpr_event_init(&ev2);
grpc_resolver_next( call_resolver_next_after_locking(
&exec_ctx, resolver, &result, &exec_ctx, resolver, &result,
grpc_closure_create(on_done, &ev2, grpc_schedule_on_exec_ctx)); grpc_closure_create(on_done, &ev2, grpc_schedule_on_exec_ctx));
grpc_exec_ctx_flush(&exec_ctx); grpc_exec_ctx_flush(&exec_ctx);
@ -126,6 +160,7 @@ int main(int argc, char **argv) {
grpc_channel_args_destroy(&exec_ctx, result); grpc_channel_args_destroy(&exec_ctx, result);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test"); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
grpc_shutdown(); grpc_shutdown();

@ -36,8 +36,11 @@
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/iomgr/combiner.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
static grpc_combiner *g_combiner;
static void test_succeeds(grpc_resolver_factory *factory, const char *string) { static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *uri = grpc_uri_parse(string, 0); grpc_uri *uri = grpc_uri_parse(string, 0);
@ -48,6 +51,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri); GPR_ASSERT(uri);
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.uri = uri; args.uri = uri;
args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args); resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver != NULL); GPR_ASSERT(resolver != NULL);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
@ -65,6 +69,7 @@ static void test_fails(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri); GPR_ASSERT(uri);
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.uri = uri; args.uri = uri;
args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args); resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver == NULL); GPR_ASSERT(resolver == NULL);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
@ -76,6 +81,8 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
grpc_init(); grpc_init();
g_combiner = grpc_combiner_create(NULL);
dns = grpc_resolver_factory_lookup("dns"); dns = grpc_resolver_factory_lookup("dns");
test_succeeds(dns, "dns:10.2.1.1"); test_succeeds(dns, "dns:10.2.1.1");
@ -84,6 +91,11 @@ int main(int argc, char **argv) {
test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888"); test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
grpc_resolver_factory_unref(dns); grpc_resolver_factory_unref(dns);
{
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
grpc_exec_ctx_finish(&exec_ctx);
}
grpc_shutdown(); grpc_shutdown();
return 0; return 0;

@ -39,9 +39,12 @@
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/combiner.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
static grpc_combiner *g_combiner;
typedef struct on_resolution_arg { typedef struct on_resolution_arg {
char *expected_server_name; char *expected_server_name;
grpc_channel_args *resolver_result; grpc_channel_args *resolver_result;
@ -62,6 +65,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri); GPR_ASSERT(uri);
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.uri = uri; args.uri = uri;
args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args); resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver != NULL); GPR_ASSERT(resolver != NULL);
@ -71,7 +75,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_closure *on_resolution = grpc_closure_create( grpc_closure *on_resolution = grpc_closure_create(
on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx); on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx);
grpc_resolver_next(&exec_ctx, resolver, &on_res_arg.resolver_result, grpc_resolver_next_locked(&exec_ctx, resolver, &on_res_arg.resolver_result,
on_resolution); on_resolution);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds"); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
@ -88,6 +92,7 @@ static void test_fails(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri); GPR_ASSERT(uri);
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.uri = uri; args.uri = uri;
args.combiner = g_combiner;
resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args); resolver = grpc_resolver_factory_create_resolver(&exec_ctx, factory, &args);
GPR_ASSERT(resolver == NULL); GPR_ASSERT(resolver == NULL);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
@ -99,6 +104,8 @@ int main(int argc, char **argv) {
grpc_test_init(argc, argv); grpc_test_init(argc, argv);
grpc_init(); grpc_init();
g_combiner = grpc_combiner_create(NULL);
ipv4 = grpc_resolver_factory_lookup("ipv4"); ipv4 = grpc_resolver_factory_lookup("ipv4");
ipv6 = grpc_resolver_factory_lookup("ipv6"); ipv6 = grpc_resolver_factory_lookup("ipv6");
@ -118,6 +125,12 @@ int main(int argc, char **argv) {
grpc_resolver_factory_unref(ipv4); grpc_resolver_factory_unref(ipv4);
grpc_resolver_factory_unref(ipv6); grpc_resolver_factory_unref(ipv6);
{
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_COMBINER_UNREF(&exec_ctx, g_combiner, "test");
grpc_exec_ctx_finish(&exec_ctx);
}
grpc_shutdown(); grpc_shutdown();
return 0; return 0;

@ -213,7 +213,7 @@ static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx,
r->channel_args = grpc_channel_args_copy(args->args); r->channel_args = grpc_channel_args_copy(args->args);
r->addresses = addresses; r->addresses = addresses;
gpr_mu_init(&r->mu); gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &fake_resolver_vtable); grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner);
return &r->base; return &r->base;
} }

@ -205,7 +205,7 @@ static void test_request(grpc_end2end_test_config config) {
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"), return grpc_error_set_int(GRPC_ERROR_CREATE("access denied"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_PERMISSION_DENIED); GRPC_STATUS_PERMISSION_DENIED);

@ -230,7 +230,7 @@ static void start_transport_stream_op(grpc_exec_ctx *exec_ctx,
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -260,7 +260,7 @@ static void test_request(grpc_end2end_test_config config) {
static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx, static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem, grpc_call_element *elem,
grpc_call_element_args *args) { const grpc_call_element_args *args) {
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -55,7 +55,7 @@ class MyCallData : public CallData {
MyCallData() {} MyCallData() {}
grpc_error* Init(grpc_exec_ctx* exec_ctx, ChannelData* channel_data, grpc_error* Init(grpc_exec_ctx* exec_ctx, ChannelData* channel_data,
grpc_call_element_args* args) override { const grpc_call_element_args* args) override {
(void)args->path; // Make sure field is available. (void)args->path; // Make sure field is available.
return GRPC_ERROR_NONE; return GRPC_ERROR_NONE;
} }

@ -0,0 +1,382 @@
/*
*
* 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.
*
*/
/* This benchmark exists to ensure that the benchmark integration is
* working */
#include <string.h>
#include <sstream>
#include <grpc++/support/channel_arguments.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
extern "C" {
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/load_reporting/load_reporting_filter.h"
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/compress_filter.h"
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/channel/deadline_filter.h"
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/channel/message_size_filter.h"
#include "src/core/lib/transport/transport_impl.h"
}
#include "third_party/benchmark/include/benchmark/benchmark.h"
static struct Init {
Init() { grpc_init(); }
~Init() { grpc_shutdown(); }
} g_init;
static void BM_InsecureChannelWithDefaults(benchmark::State &state) {
grpc_channel *channel =
grpc_insecure_channel_create("localhost:12345", NULL, NULL);
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
grpc_slice method = grpc_slice_from_static_string("/foo/bar");
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
while (state.KeepRunning()) {
grpc_call_destroy(grpc_channel_create_call(channel, NULL,
GRPC_PROPAGATE_DEFAULTS, cq,
method, NULL, deadline, NULL));
}
grpc_channel_destroy(channel);
grpc_completion_queue_destroy(cq);
}
BENCHMARK(BM_InsecureChannelWithDefaults);
static void FilterDestroy(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
gpr_free(arg);
}
static void DoNothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
class FakeClientChannelFactory : public grpc_client_channel_factory {
public:
FakeClientChannelFactory() { vtable = &vtable_; }
private:
static void NoRef(grpc_client_channel_factory *factory) {}
static void NoUnref(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory) {}
static grpc_subchannel *CreateSubchannel(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory,
const grpc_subchannel_args *args) {
return nullptr;
}
static grpc_channel *CreateClientChannel(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory,
const char *target,
grpc_client_channel_type type,
const grpc_channel_args *args) {
return nullptr;
}
static const grpc_client_channel_factory_vtable vtable_;
};
const grpc_client_channel_factory_vtable FakeClientChannelFactory::vtable_ = {
NoRef, NoUnref, CreateSubchannel, CreateClientChannel};
static grpc_arg StringArg(const char *key, const char *value) {
grpc_arg a;
a.type = GRPC_ARG_STRING;
a.key = const_cast<char *>(key);
a.value.string = const_cast<char *>(value);
return a;
}
enum FixtureFlags : uint32_t {
CHECKS_NOT_LAST = 1,
REQUIRES_TRANSPORT = 2,
};
template <const grpc_channel_filter *kFilter, uint32_t kFlags>
struct Fixture {
const grpc_channel_filter *filter = kFilter;
const uint32_t flags = kFlags;
};
namespace dummy_filter {
static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_transport_stream_op *op) {}
static void StartTransportOp(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_transport_op *op) {}
static grpc_error *InitCallElem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_element_args *args) {
return GRPC_ERROR_NONE;
}
static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
grpc_polling_entity *pollent) {}
static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
void *and_free_memory) {}
grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) {
return GRPC_ERROR_NONE;
}
void DestroyChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
return gpr_strdup("peer");
}
void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
const grpc_channel_info *channel_info) {}
static const grpc_channel_filter dummy_filter = {StartTransportStreamOp,
StartTransportOp,
0,
InitCallElem,
SetPollsetOrPollsetSet,
DestroyCallElem,
0,
InitChannelElem,
DestroyChannelElem,
GetPeer,
GetChannelInfo,
"dummy_filter"};
} // namespace dummy_filter
namespace dummy_transport {
/* Memory required for a single stream element - this is allocated by upper
layers and initialized by the transport */
size_t sizeof_stream; /* = sizeof(transport stream) */
/* name of this transport implementation */
const char *name;
/* implementation of grpc_transport_init_stream */
int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_stream_refcount *refcount,
const void *server_data) {
return 0;
}
/* implementation of grpc_transport_set_pollset */
void SetPollset(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_pollset *pollset) {}
/* implementation of grpc_transport_set_pollset */
void SetPollsetSet(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_pollset_set *pollset_set) {}
/* implementation of grpc_transport_perform_stream_op */
void PerformStreamOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_transport_stream_op *op) {
grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_NONE);
}
/* implementation of grpc_transport_perform_op */
void PerformOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_transport_op *op) {}
/* implementation of grpc_transport_destroy_stream */
void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, void *and_free_memory) {}
/* implementation of grpc_transport_destroy */
void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
/* implementation of grpc_transport_get_peer */
char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
return gpr_strdup("transport_peer");
}
/* implementation of grpc_transport_get_endpoint */
grpc_endpoint *GetEndpoint(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
return nullptr;
}
static const grpc_transport_vtable dummy_transport_vtable = {
0, "dummy_http2", InitStream,
SetPollset, SetPollsetSet, PerformStreamOp,
PerformOp, DestroyStream, Destroy,
GetPeer, GetEndpoint};
static grpc_transport dummy_transport = {&dummy_transport_vtable};
} // namespace dummy_transport
class NoOp {
public:
class Op {
public:
Op(grpc_exec_ctx *exec_ctx, NoOp *p, grpc_call_stack *s) {}
void Finish(grpc_exec_ctx *exec_ctx) {}
};
};
class SendEmptyMetadata {
public:
SendEmptyMetadata() {
memset(&op_, 0, sizeof(op_));
op_.on_complete = grpc_closure_init(&closure_, DoNothing, nullptr,
grpc_schedule_on_exec_ctx);
}
class Op {
public:
Op(grpc_exec_ctx *exec_ctx, SendEmptyMetadata *p, grpc_call_stack *s) {
grpc_metadata_batch_init(&batch_);
p->op_.send_initial_metadata = &batch_;
}
void Finish(grpc_exec_ctx *exec_ctx) {
grpc_metadata_batch_destroy(exec_ctx, &batch_);
}
private:
grpc_metadata_batch batch_;
};
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
const gpr_timespec start_time_ = gpr_now(GPR_CLOCK_MONOTONIC);
const grpc_slice method_ = grpc_slice_from_static_string("/foo/bar");
grpc_transport_stream_op op_;
grpc_closure closure_;
};
// Test a filter in isolation. Fixture specifies the filter under test (use the
// Fixture<> template to specify this), and TestOp defines some unit of work to
// perform on said filter.
template <class Fixture, class TestOp>
static void BM_IsolatedFilter(benchmark::State &state) {
Fixture fixture;
std::ostringstream label;
std::vector<grpc_arg> args;
FakeClientChannelFactory fake_client_channel_factory;
args.push_back(grpc_client_channel_factory_create_channel_arg(
&fake_client_channel_factory));
args.push_back(StringArg(GRPC_ARG_SERVER_URI, "localhost"));
grpc_channel_args channel_args = {args.size(), &args[0]};
std::vector<const grpc_channel_filter *> filters;
if (fixture.filter != nullptr) {
filters.push_back(fixture.filter);
}
if (fixture.flags & CHECKS_NOT_LAST) {
filters.push_back(&dummy_filter::dummy_filter);
label << " #has_dummy_filter";
}
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
size_t channel_size = grpc_channel_stack_size(&filters[0], filters.size());
grpc_channel_stack *channel_stack =
static_cast<grpc_channel_stack *>(gpr_malloc(channel_size));
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"call_stack_init",
grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack,
&filters[0], filters.size(), &channel_args,
fixture.flags & REQUIRES_TRANSPORT
? &dummy_transport::dummy_transport
: nullptr,
"CHANNEL", channel_stack)));
grpc_exec_ctx_flush(&exec_ctx);
grpc_call_stack *call_stack = static_cast<grpc_call_stack *>(
gpr_malloc(channel_stack->call_stack_size));
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
grpc_slice method = grpc_slice_from_static_string("/foo/bar");
grpc_call_final_info final_info;
TestOp test_op_data;
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1,
DoNothing, NULL, NULL, NULL, method,
start_time, deadline, call_stack));
typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack);
grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL);
op.Finish(&exec_ctx);
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_channel_stack_destroy(&exec_ctx, channel_stack);
grpc_exec_ctx_finish(&exec_ctx);
gpr_free(channel_stack);
gpr_free(call_stack);
state.SetLabel(label.str());
}
typedef Fixture<nullptr, 0> NoFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, NoFilter, NoOp);
typedef Fixture<&dummy_filter::dummy_filter, 0> DummyFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, DummyFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, DummyFilter, SendEmptyMetadata);
typedef Fixture<&grpc_client_channel_filter, 0> ClientChannelFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientChannelFilter, NoOp);
typedef Fixture<&grpc_compress_filter, CHECKS_NOT_LAST> CompressFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, SendEmptyMetadata);
typedef Fixture<&grpc_client_deadline_filter, CHECKS_NOT_LAST>
ClientDeadlineFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientDeadlineFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientDeadlineFilter, SendEmptyMetadata);
typedef Fixture<&grpc_server_deadline_filter, CHECKS_NOT_LAST>
ServerDeadlineFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, ServerDeadlineFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, ServerDeadlineFilter, SendEmptyMetadata);
typedef Fixture<&grpc_http_client_filter, CHECKS_NOT_LAST | REQUIRES_TRANSPORT>
HttpClientFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpClientFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpClientFilter, SendEmptyMetadata);
typedef Fixture<&grpc_http_server_filter, CHECKS_NOT_LAST> HttpServerFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, SendEmptyMetadata);
typedef Fixture<&grpc_message_size_filter, CHECKS_NOT_LAST> MessageSizeFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, SendEmptyMetadata);
typedef Fixture<&grpc_load_reporting_filter, CHECKS_NOT_LAST>
LoadReportingFilter;
BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
BENCHMARK_MAIN();

@ -0,0 +1,248 @@
/*
*
* 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.
*
*/
/* Test various operations on grpc_error */
#include <memory>
extern "C" {
#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/transport/error_utils.h"
}
#include "third_party/benchmark/include/benchmark/benchmark.h"
class ErrorDeleter {
public:
void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); }
};
typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
static void BM_ErrorCreate(benchmark::State& state) {
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_CREATE("Error"));
}
}
BENCHMARK(BM_ErrorCreate);
static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_ABORTED));
}
}
BENCHMARK(BM_ErrorCreateAndSetStatus);
static void BM_ErrorRefUnref(benchmark::State& state) {
grpc_error* error = GRPC_ERROR_CREATE("Error");
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_REF(error));
}
GRPC_ERROR_UNREF(error);
}
BENCHMARK(BM_ErrorRefUnref);
static void BM_ErrorUnrefNone(benchmark::State& state) {
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_NONE);
}
}
BENCHMARK(BM_ErrorUnrefNone);
static void BM_ErrorGetIntFromNoError(benchmark::State& state) {
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value);
}
}
BENCHMARK(BM_ErrorGetIntFromNoError);
static void BM_ErrorGetMissingInt(benchmark::State& state) {
ErrorPtr error(
grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_INDEX, 1));
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
}
}
BENCHMARK(BM_ErrorGetMissingInt);
static void BM_ErrorGetPresentInt(benchmark::State& state) {
ErrorPtr error(
grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_OFFSET, 1));
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
}
}
BENCHMARK(BM_ErrorGetPresentInt);
// Fixtures for tests: generate different kinds of errors
class ErrorNone {
public:
gpr_timespec deadline() const { return deadline_; }
grpc_error* error() const { return GRPC_ERROR_NONE; }
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
};
class ErrorCancelled {
public:
gpr_timespec deadline() const { return deadline_; }
grpc_error* error() const { return GRPC_ERROR_CANCELLED; }
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
};
class SimpleError {
public:
gpr_timespec deadline() const { return deadline_; }
grpc_error* error() const { return error_.get(); }
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
ErrorPtr error_{GRPC_ERROR_CREATE("Error")};
};
class ErrorWithGrpcStatus {
public:
gpr_timespec deadline() const { return deadline_; }
grpc_error* error() const { return error_.get(); }
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
ErrorPtr error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_UNIMPLEMENTED)};
};
class ErrorWithHttpError {
public:
gpr_timespec deadline() const { return deadline_; }
grpc_error* error() const { return error_.get(); }
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
ErrorPtr error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
GRPC_ERROR_INT_HTTP2_ERROR,
GRPC_HTTP2_COMPRESSION_ERROR)};
};
class ErrorWithNestedGrpcStatus {
public:
gpr_timespec deadline() const { return deadline_; }
grpc_error* error() const { return error_.get(); }
private:
const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
ErrorPtr nested_error_{grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_UNIMPLEMENTED)};
grpc_error* nested_errors_[1] = {nested_error_.get()};
ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING("Error", nested_errors_, 1)};
};
template <class Fixture>
static void BM_ErrorStringOnNewError(benchmark::State& state) {
while (state.KeepRunning()) {
Fixture fixture;
grpc_error_string(fixture.error());
}
}
template <class Fixture>
static void BM_ErrorStringRepeatedly(benchmark::State& state) {
Fixture fixture;
while (state.KeepRunning()) {
grpc_error_string(fixture.error());
}
}
template <class Fixture>
static void BM_ErrorGetStatus(benchmark::State& state) {
Fixture fixture;
while (state.KeepRunning()) {
grpc_status_code status;
const char* msg;
grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &msg,
NULL);
}
}
template <class Fixture>
static void BM_ErrorGetStatusCode(benchmark::State& state) {
Fixture fixture;
while (state.KeepRunning()) {
grpc_status_code status;
grpc_error_get_status(fixture.error(), fixture.deadline(), &status, NULL,
NULL);
}
}
template <class Fixture>
static void BM_ErrorHttpError(benchmark::State& state) {
Fixture fixture;
while (state.KeepRunning()) {
grpc_http2_error_code error;
grpc_error_get_status(fixture.error(), fixture.deadline(), NULL, NULL,
&error);
}
}
template <class Fixture>
static void BM_HasClearGrpcStatus(benchmark::State& state) {
Fixture fixture;
while (state.KeepRunning()) {
grpc_error_has_clear_grpc_status(fixture.error());
}
}
#define BENCHMARK_SUITE(fixture) \
BENCHMARK_TEMPLATE(BM_ErrorStringOnNewError, fixture); \
BENCHMARK_TEMPLATE(BM_ErrorStringRepeatedly, fixture); \
BENCHMARK_TEMPLATE(BM_ErrorGetStatus, fixture); \
BENCHMARK_TEMPLATE(BM_ErrorGetStatusCode, fixture); \
BENCHMARK_TEMPLATE(BM_ErrorHttpError, fixture); \
BENCHMARK_TEMPLATE(BM_HasClearGrpcStatus, fixture)
BENCHMARK_SUITE(ErrorNone);
BENCHMARK_SUITE(ErrorCancelled);
BENCHMARK_SUITE(SimpleError);
BENCHMARK_SUITE(ErrorWithGrpcStatus);
BENCHMARK_SUITE(ErrorWithHttpError);
BENCHMARK_SUITE(ErrorWithNestedGrpcStatus);
BENCHMARK_MAIN();

@ -37,8 +37,11 @@ cc_library(
hdrs = [ hdrs = [
"test_config.h", "test_config.h",
], ],
deps = ["//:gpr"],
visibility = ["//test:__subpackages__"], visibility = ["//test:__subpackages__"],
deps = [
"//:gpr",
"//external:gflags",
],
) )
cc_library( cc_library(
@ -58,6 +61,10 @@ cc_library(
"subprocess.h", "subprocess.h",
"test_credentials_provider.h", "test_credentials_provider.h",
], ],
deps = ["//test/core/util:gpr_test_util", "//:grpc++", "//test/core/end2end:ssl_test_data"],
visibility = ["//test:__subpackages__"], visibility = ["//test:__subpackages__"],
deps = [
"//:grpc++",
"//test/core/end2end:ssl_test_data",
"//test/core/util:gpr_test_util",
],
) )

@ -1 +1 @@
Subproject commit f8a0efe03aa69b3336d8e228b37d4ccb17324b88 Subproject commit 30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e

@ -26,76 +26,77 @@ RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3 && \
rvmsudo rvm cleanup all " rvmsudo rvm cleanup all "
# Regenerate the following using build.sh if the build folder changes. # Regenerate the following using build.sh if the build folder changes.
RUN echo \ RUN echo \\
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\
si7rsi7r8qcs/w8AInVFAFAAAA==\ LgyDM2eUPZUhHiPhq3nPpyMmqnJ1isXssiHZtBRNovV9+cYSSiihhBJKKKGEEkoooYQSSiihhBJK\
KKGEEkoooYQSSiihhBJKKKGEEkoooYQSSiihhH9H+D9i0BbqAHgAAA==\
| base64 -d | tar xzC /tmp | base64 -d | tar xzC /tmp
# Import patch files for ruby and gems # Import patch files for ruby and gems
@ -105,7 +106,9 @@ ENV BASH_ENV /etc/rubybashrc
# install rubies and fix permissions on # install rubies and fix permissions on
RUN bash -c " \ RUN bash -c " \
export CFLAGS='-s -O3 -fno-fast-math -fPIC' && \ export CFLAGS='-s -O3 -fno-fast-math -fPIC' && \
for v in 2.3.0 ; do \ echo 'about to install patches for ruby 2.4.0 from:' && \
ls -r ~/patches && \
for v in 2.4.0 ; do \
rvm install \$v --patch \$(echo ~/patches/ruby-\$v/* | tr ' ' ','); \ rvm install \$v --patch \$(echo ~/patches/ruby-\$v/* | tr ' ' ','); \
done && \ done && \
rvm cleanup all && \ rvm cleanup all && \
@ -116,20 +119,26 @@ RUN bash -c " \
RUN echo "gem: --no-ri --no-rdoc" >> ~/.gemrc && \ RUN echo "gem: --no-ri --no-rdoc" >> ~/.gemrc && \
bash -c " \ bash -c " \
rvm all do gem install bundler rake-compiler hoe mini_portile rubygems-tasks && \ rvm all do gem install bundler rake-compiler hoe mini_portile rubygems-tasks && \
rvm 2.3.0 do gem install mini_portile2 && \ rvm 2.4.0 do gem install mini_portile2 && \
find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw " find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
RUN bash -c "gem env"
RUN bash -c "gem list rake-compiler"
# Install rake-compiler's cross rubies in global dir instead of /root # Install rake-compiler's cross rubies in global dir instead of /root
RUN sudo mkdir -p /usr/local/rake-compiler && \ RUN sudo mkdir -p /usr/local/rake-compiler && \
sudo chown rvm.rvm /usr/local/rake-compiler && \ sudo chown rvm.rvm /usr/local/rake-compiler && \
ln -s /usr/local/rake-compiler ~/.rake-compiler ln -s /usr/local/rake-compiler ~/.rake-compiler
# Patch rake-compiler to avoid build of ruby extensions # Patch rake-compiler to avoid build of ruby extensions
RUN cd /usr/local/rvm/gems/ruby-2.3.0/gems/rake-compiler-0.9.5 && git apply /home/rvm/patches/rake-compiler-0.9.5/*.diff ; \ RUN cd /usr/local/rvm/gems/ruby-2.4.0/gems/rake-compiler-0.9.5 && git apply /home/rvm/patches/rake-compiler-0.9.5/*.diff ; \
true true
RUN bash -c "rvm use 2.3.0 --default && \ RUN bash -c "rvm use 2.4.0 --default && \
export MAKE=\"make -j`nproc`\" CFLAGS='-s -O1 -fno-omit-frame-pointer -fno-fast-math' && \ export MAKE=\"make -j`nproc`\" CFLAGS='-s -O1 -fno-omit-frame-pointer -fno-fast-math' && \
rake-compiler cross-ruby VERSION=2.4.0 HOST=i686-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.4.0 HOST=x86_64-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.4.0 HOST=x86_64-linux-gnu && \
rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-w64-mingw32 && \ rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-w64-mingw32 && \ rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-w64-mingw32 && \
rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-linux-gnu && \ rake-compiler cross-ruby VERSION=2.3.0 HOST=x86_64-linux-gnu && \
@ -145,8 +154,9 @@ RUN bash -c "rvm use 2.3.0 --default && \
rm -rf ~/.rake-compiler/tmp/builds ~/.rake-compiler/sources && \ rm -rf ~/.rake-compiler/tmp/builds ~/.rake-compiler/sources && \
find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw " find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
RUN bash -c "rvm use 2.3.0 --default && \ RUN bash -c "rvm use 2.4.0 --default && \
export MAKE=\"make -j`nproc`\" CFLAGS='-m32 -s -O1 -fno-omit-frame-pointer -fno-fast-math' LDFLAGS='-m32' && \ export MAKE=\"make -j`nproc`\" CFLAGS='-m32 -s -O1 -fno-omit-frame-pointer -fno-fast-math' LDFLAGS='-m32' && \
rake-compiler cross-ruby VERSION=2.4.0 HOST=i686-linux-gnu && \
rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-linux-gnu && \ rake-compiler cross-ruby VERSION=2.3.0 HOST=i686-linux-gnu && \
rake-compiler cross-ruby VERSION=2.2.2 HOST=i686-linux-gnu && \ rake-compiler cross-ruby VERSION=2.2.2 HOST=i686-linux-gnu && \
rake-compiler cross-ruby VERSION=2.1.5 HOST=i686-linux-gnu && \ rake-compiler cross-ruby VERSION=2.1.5 HOST=i686-linux-gnu && \
@ -155,7 +165,7 @@ RUN bash -c "rvm use 2.3.0 --default && \
find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw " find /usr/local/rvm -type d -print0 | sudo xargs -0 chmod g+sw "
RUN bash -c " \ RUN bash -c " \
rvm alias create 2.3 2.3.0 " rvm alias create 2.4 2.4.0 "
USER root USER root
@ -167,6 +177,7 @@ RUN sed -i -- "s:/root/.rake-compiler:/usr/local/rake-compiler:g" /usr/local/rak
# Install wrappers for strip commands as a workaround for "Protocol error" in boot2docker. # Install wrappers for strip commands as a workaround for "Protocol error" in boot2docker.
RUN cp /tmp/build/strip_wrapper /root/ RUN cp /tmp/build/strip_wrapper /root/
RUN sudo chmod +rx /root/strip_wrapper
RUN mv /opt/mingw/mingw32/bin/i686-w64-mingw32-strip /opt/mingw/mingw32/bin/i686-w64-mingw32-strip.bin && \ RUN mv /opt/mingw/mingw32/bin/i686-w64-mingw32-strip /opt/mingw/mingw32/bin/i686-w64-mingw32-strip.bin && \
mv /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip.bin && \ mv /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip /opt/mingw/mingw64/bin/x86_64-w64-mingw32-strip.bin && \
mv /usr/bin/i686-w64-mingw32-strip /usr/bin/i686-w64-mingw32-strip.bin && \ mv /usr/bin/i686-w64-mingw32-strip /usr/bin/i686-w64-mingw32-strip.bin && \
@ -196,6 +207,10 @@ RUN cp /tmp/build/runas /usr/local/bin/
# Install sudoers configuration # Install sudoers configuration
RUN cp /tmp/build/sudoers /etc/sudoers.d/rake-compiler-dock RUN cp /tmp/build/sudoers /etc/sudoers.d/rake-compiler-dock
ENV RUBY_CC_VERSION 2.3.0:2.2.2:2.1.5:2.0.0 # Fixup Ruby 2.4 'static' compilation issue.
RUN echo '!<arch>' > /usr/local/rake-compiler/ruby/x86_64-linux-gnu/ruby-2.4.0/lib/libruby.a
RUN echo '!<arch>' > /usr/local/rake-compiler/ruby/i686-linux-gnu/ruby-2.4.0/lib/libruby.a
ENV RUBY_CC_VERSION 2.4.0:2.3.0:2.2.2:2.1.5:2.0.0
CMD bash CMD bash

@ -0,0 +1,12 @@
diff --git a/configure b/configure
index ebe3d8c..a336b73 100755
--- a/configure
+++ b/configure
@@ -18943,7 +18943,6 @@ do :
ac_fn_c_check_func "$LINENO" "sendfile" "ac_cv_func_sendfile"
if test "x$ac_cv_func_sendfile" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_SENDFILE 1
_ACEOF
fi

@ -34,7 +34,7 @@ rm -rf ~/.rake-compiler
CROSS_RUBY=`mktemp tmpfile.XXXXXXXX` CROSS_RUBY=`mktemp tmpfile.XXXXXXXX`
curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v0.9.5/tasks/bin/cross-ruby.rake > $CROSS_RUBY curl https://raw.githubusercontent.com/rake-compiler/rake-compiler/v1.0.3/tasks/bin/cross-ruby.rake > $CROSS_RUBY
patch $CROSS_RUBY << EOF patch $CROSS_RUBY << EOF
--- cross-ruby.rake 2016-02-05 16:26:53.000000000 -0800 --- cross-ruby.rake 2016-02-05 16:26:53.000000000 -0800
@ -53,7 +53,8 @@ EOF
MAKE="make -j8" MAKE="make -j8"
for v in 2.3.0 2.2.2 2.1.5 2.0.0-p645 ; do for v in 2.4.0 2.3.0 2.2.2 2.1.5 2.0.0-p645 ; do
ccache -c
rake -f $CROSS_RUBY cross-ruby VERSION=$v HOST=x86_64-darwin11 rake -f $CROSS_RUBY cross-ruby VERSION=$v HOST=x86_64-darwin11
done done

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -38,4 +38,4 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins # runtime 23 * 60 mins
config=asan-trace-cmp runtime=86400 tools/jenkins/run_fuzzer.sh api_fuzzer config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh api_fuzzer

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -37,6 +37,5 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins
config=asan-trace-cmp tools/jenkins/run_fuzzer.sh hpack_parser_fuzzer_test config=asan-trace-cmp tools/jenkins/run_fuzzer.sh hpack_parser_fuzzer_test

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -37,6 +37,5 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins
config=asan-trace-cmp tools/jenkins/run_fuzzer.sh http_request_fuzzer_test config=asan-trace-cmp tools/jenkins/run_fuzzer.sh http_request_fuzzer_test

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -37,6 +37,5 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins
config=asan-trace-cmp tools/jenkins/run_fuzzer.sh json_fuzzer_test config=asan-trace-cmp tools/jenkins/run_fuzzer.sh json_fuzzer_test

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -37,5 +37,4 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins
config=asan-trace-cmp tools/jenkins/run_fuzzer.sh nanopb_fuzzer_response_test config=asan-trace-cmp tools/jenkins/run_fuzzer.sh nanopb_fuzzer_response_test

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -38,4 +38,4 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins # runtime 23 * 60 mins
config=asan-trace-cmp runtime=86400 tools/jenkins/run_fuzzer.sh server_fuzzer config=asan-trace-cmp runtime=82800 tools/jenkins/run_fuzzer.sh server_fuzzer

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Copyright 2016, Google Inc. # Copyright 2017, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@ -37,5 +37,4 @@ git submodule update --init
# download fuzzer docker image from dockerhub # download fuzzer docker image from dockerhub
export DOCKERHUB_ORGANIZATION=grpctesting export DOCKERHUB_ORGANIZATION=grpctesting
# runtime 23 * 60 mins
config=asan-trace-cmp tools/jenkins/run_fuzzer.sh uri_fuzzer_test config=asan-trace-cmp tools/jenkins/run_fuzzer.sh uri_fuzzer_test

@ -1,5 +1,4 @@
#!/bin/bash # Copyright 2017, Google Inc.
# Copyright 2016, Google Inc.
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save